I have created my custom View in Android and trying to draw a circle in that but nothing is drawing but with no errors.
Here is my code
public class ColorOptionsView extends RelativeLayout {
private View mValue;
private ImageView mImage;
private Paint paint;
String cirlceText;
int circleColor,circleTextColor;
float circleTextSize;
public ColorOptionsView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorOptionsView, 0, 0);
try {
cirlceText = a.getString(R.styleable.ColorOptionsView_circleText);
circleColor = a.getColor(R.styleable.ColorOptionsView_circleColor, 0);
circleTextColor = a.getColor(R.styleable.ColorOptionsView_circleTextColor, 0);
circleTextSize = a.getFloat(R.styleable.ColorOptionsView_circleTextSize,20);
} finally {
a.recycle();
}
}
public void setCirlceText(String cirlceText) {
this.cirlceText = cirlceText;
invalidate();
requestLayout();
}
public void setCircleColor(int circleColor) {
this.circleColor = circleColor;
invalidate();
requestLayout();
}
public void setCircleTextColor(int circleTextColor) {
this.circleTextColor = circleTextColor;
invalidate();
requestLayout();
}
public void setCircleTextSize(float circleTextSize) {
this.circleTextSize = circleTextSize;
invalidate();
requestLayout();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setColor(circleColor);
int centerX = this.getMeasuredWidth()/2;
int centerY = this.getMeasuredHeight()/2;
int raduis = 150;
canvas.drawCircle(centerX,centerY,raduis,paint);
paint.setColor(circleTextColor);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(cirlceText,centerX,centerY,paint);
canvas.drawLine(0,100,100,0,paint);
}
I am not getting where I went wrong. Devs check it and help me out.
Related
I've followed some forums and I'm lost with this problem:
I have a Custom View that draws 9 circles for me as shown below:
This circles must be an icon to the main one and 8 images for the others and it must be a drawable resource (I have png pictures in on my drawable folder).
How may I proceed to set this drawable images instead of the colors?
This is my actual code:
public class CircleView extends View {
public static interface IMenuListener{
public void onMenuClick(MenuCircle item);
}
public static class MenuCircle{
private int x,y,radius;
public int id;
public String text;
}
private Paint mainPaint;
private Paint secondPaint;
private Paint textPaint;
private int radius_main =130;
private int menuInnerPadding = 40;
private int radialCircleRadius = 60;
private int textPadding = 25;
private double startAngle = - Math.PI/2f;
private ArrayList<MenuCircle> elements;
private IMenuListener listener;
public void setListener(IMenuListener listener){
this.listener = listener;
}
public void clear(){
elements.clear();
listener=null;
}
public CircleView(Context context) {
super(context);
init();
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
elements = new ArrayList<>();
}
public void addMenuItem(String text,int id){
MenuCircle item = new MenuCircle();
item.id = id;
item.text=text;
elements.add(item);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mainPaint = new Paint();
mainPaint.setColor(Color.DKGRAY); //color of main circle
secondPaint = new Paint();
secondPaint.setColor(Color.DKGRAY); // color of 8 circles
textPaint = new Paint();
textPaint.setColor(Color.BLACK); // text under 8 circles
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centerX = canvas.getWidth()/2 ;
int centerY= canvas.getHeight()/2;
canvas.drawCircle(centerX,centerY,radius_main,mainPaint);
for(int i=0;i<elements.size();i++){
double angle =0;
if(i==0){
angle = startAngle;
}else{
angle = startAngle+(i * ((2 * Math.PI) / elements.size()));
}
elements.get(i).x = (int) (centerX + Math.cos(angle)*(radius_main+menuInnerPadding+radialCircleRadius));
elements.get(i).y = (int) (centerY + Math.sin(angle)*(radius_main+menuInnerPadding+radialCircleRadius));
canvas.drawCircle( elements.get(i).x,elements.get(i).y,radialCircleRadius,secondPaint);
float tW = textPaint.measureText(elements.get(i).text);
canvas.drawText(elements.get(i).text,elements.get(i).x-tW/2,elements.get(i).y+radialCircleRadius+textPadding,textPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
for(MenuCircle mc : elements){
double distance = Math.hypot(event.getX()-mc.x,event.getY()-mc.y);
if(distance<= radialCircleRadius){
//touched
if(listener!=null)
listener.onMenuClick(mc);
return true;
}
}
}
return super.onTouchEvent(event);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
}
Can you Give me any advice how to draw a list of rectangles?
I have a Rectangle class :
public final class Rectangle extends View {
private Rect rectangle;
private Paint paint;
public Rectangle(Context context) {
super(context);
int x = 50;
int y = 50;
int sideLength = 200;
// create a rectangle that we'll draw later
rectangle = new Rect(x, y, sideLength, sideLength);
// create the Paint and set its color
paint = new Paint();
paint.setColor(Color.GRAY);
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(Color.BLUE);
canvas.drawRect(rectangle, paint);
}
}
and a Rectangle instance on activity
setContentView(new Rectangle(this));
Here you have some example three rectangles side by side
public class Rectangles extends View {
private Paint paintBlack;
public Rectangles(Context context) {
super(context);
init();
}
public Rectangles(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Rectangles(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paintBlack = new Paint();
paintBlack.setColor(Color.BLACK);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, 100, 100, paintBlack);
canvas.drawRect(105, 0, 205, 100, paintBlack);
canvas.drawRect(210, 0, 310, 100, paintBlack);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(500, 500);
}
}
i want to know if i'm able to change the color of the active tab indicator (that light-blue line) to black(#4A4A4A)
Here is the photo
public class PageIndicator extends View {
int totalNoOfDots;
int activeDot;
int dotSpacing;
int horizontalSpace = 5;
Bitmap activeDotBitmap;
Bitmap normalDotBitmap;
int x = 0;
private Paint paint;
public PageIndicator(Context context) {
super(context);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
activeDotBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dot_active);
normalDotBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dot_normal);
}
public PageIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
activeDotBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dot_active);
normalDotBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dot_normal);
}
public PageIndicator(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
activeDotBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dot_active);
normalDotBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dot_normal);
}
#Override
protected void onDraw(Canvas canvas) {
drawDot(canvas);
super.onDraw(canvas);
}
private void drawDot(Canvas canvas) {
for (int i = 0; i < totalNoOfDots; i++) {
if (i == activeDot) {
canvas.drawBitmap(activeDotBitmap, x, 0, paint);
} else {
canvas.drawBitmap(normalDotBitmap, x, 0, paint);
}
x = x + activeDotBitmap.getWidth() + horizontalSpace + dotSpacing;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = totalNoOfDots * (activeDotBitmap.getWidth() + horizontalSpace + getDotSpacing());
width = resolveSize(width, widthMeasureSpec);
int height = activeDotBitmap.getHeight();
height = resolveSize(height, heightMeasureSpec);
setMeasuredDimension(width, height);
}
public void refersh() {
x = 0;
invalidate();
}
public int getTotalNoOfDots() {
return totalNoOfDots;
}
public void setTotalNoOfDots(int totalNoOfDots) {
this.totalNoOfDots = totalNoOfDots;
x = 0;
invalidate();
}
public int getActiveDot() {
return activeDot;
}
public void setActiveDot(int activeDot) {
this.activeDot = activeDot;
x = 0;
invalidate();
}
public int getDotSpacing() {
return dotSpacing;
}
public void setDotSpacing(int dotSpacing) {
this.dotSpacing = dotSpacing;
x = 0;
invalidate();
}
}
if you are using support library.
add this to your tabLayout
app:tabIndicatorColor="#4A4A4A"
the idea is, i want to make animated kanji letter (in sequence) like this project HTML5 Stroke Animation. And my problem is, when i call onDraw method my canvas just draw simultaneously. I couldn't find much info about it on the internet, so any clue would be much appreciated if you have already come across the same situation.
here is my code:
public class MainActivity extends AppCompatActivity {
private TextView txt;
private SvgPathParser svgPathParser;
private PathView pathView;
private String sPath =
"M32.49,17.39c0.14,1.08,0.24,2.44-0.12,3.77c-2.29,8.41-11.14,24.16-21.81,35.56" +
"|M25.03,42c0.59,0.61,0.76,1.97,0.76,3.23c0,10.08,0.08,28.85,0,40.77c-0.02,3.48-0.04,6.4-0.04,8.38" +
"|M55.1,14.25c0.05,0.65,0.16,1.69-0.09,2.6c-1.55,5.6-8.51,16.02-17.36,24.43" +
"|M53.88,27.02c0.94,0.18,3.7,0.29,4.62,0.18c4.47-0.52,18.49-2.45,26.44-3.62c2.43-0.36,4.03-0.45,6.45-0.17" +
"|M52.82,39.44c1.03,0.85,1.4,3.75,0.72,5.89c-3.37,10.67-6.4,19.7-11.35,30.04c-1.45,3.03-0.49,4.25,1.47,4.33c10.84,0.43,18.96,1.05,29.44,3.78c5.98,1.55,12.27,4.02,17.89,7.93" +
"|M54.69,42.07c6.68-0.95,22.21-3.14,26.69-3.43c3.45-0.22,4.43,1.81,4.14,4.54c-1.33,12.48-5.94,37.8-10.23,47.46c-2.3,5.17-4.97,4.12-7.54,1.33" +
"|M68.32,43.35c0.45,0.88,0.63,2.39,0.13,4.22c-2.32,8.56-7.53,25.28-10.01,32.34" +
"|M32.07,61.64c3.43,0.61,5.94,0.44,8.42,0.17c12.25-1.31,31.7-3.07,49-3.92c2.76-0.14,5.75-0.41,8.43,0.38";
String[] arrayPath = sPath.split("\\|");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new PathView(this));
}
private Path path(String sPath) throws ParseException {
svgPathParser = new SvgPathParser();
return svgPathParser.parsePath(sPath);
}
public class PathView extends View {
Path path;
Paint paint;
List<Path> paths;
float length;
public PathView(Context context) {
super(context);
init();
}
public PathView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void init() {
paths = new ArrayList<>();
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
for (int i = 0; i < arrayPath.length; i++) {
try {
paths.add(path(arrayPath[i]));
// path = );
} catch (ParseException e) {
e.printStackTrace();
}
}
// Measure the path
for (Path path : paths) {
this.path = path;
PathMeasure measure = new PathMeasure(path, false);
length = measure.getLength();
float[] intervals = new float[]{length, length};
ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);
animator.setDuration(2000);
animator.start();
}
}
//is called by animtor object
public void setPhase(float phase) {
Log.d("pathview", "setPhase called with:" + String.valueOf(phase));
paint.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();//will calll onDraw
}
private PathEffect createPathEffect(float pathLength, float phase, float offset) {
return new DashPathEffect(new float[]{pathLength, pathLength},
Math.max(phase * pathLength, offset));
}
#Override
public void onDraw(Canvas c) {
super.onDraw(c);
for (Path path : paths) {
this.path = path;
c.drawPath(path, paint);
}
}
}
}
I have following TextView
public class Cube extends TextView {
Context mContext;
Drawable background;//Hintergrund des Blocks
char mLetter;//Buchstabe des Blocks
int x, y;//Koordinaten des Blocks
#SuppressWarnings("deprecation")
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public Cube(Context context, char letter, int _x, int _y) {
super(context);
mContext = context;
mLetter = letter;
background = ContextCompat.getDrawable(getContext(), R.drawable.cube);
x = _x;
y = _y;
this.setText("" + letter);
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN)
this.setBackgroundDrawable(background);
else
this.setBackground(background);
}
public void drawCube(Canvas canvas){//how to draw now!? This is called from a separate thread in SurfaceView
}
}
If I call following in drawCube():
background.setBounds(x, y, x + 20, y + 20);
background.draw(canvas);
it just draws the backgroundDrawable. But how can I draw it with the text/the letter inside? That it looks like this: (The background ist the canvas, the orange and white one is the Background and the "A" is the letter/text)
EDIT: Code at 21.09
This is my (shortened) thread:
public class CanvasThread extends Thread {
private SurfaceHolder mSh;
private ArrayList<Cube> mCubes;
private Canvas mCanvas;
private Context mContext;
private boolean mRun = false;
private boolean mDown = false;
private boolean newCube = false;
public CanvasThread(SurfaceHolder sh, Context context){
mSh = sh;
mCubes = new ArrayList<>();
mContext = context;
}
public void run(){
while(mRun){
mCanvas = null;
try{
mCanvas = mSh.lockCanvas(null);
synchronized (mSh){
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
newCube = true;
for(int i = 0; i < mCubes.size(); i++){
if(mCubes.get(i).getSpeed() > 0)
newCube = false;
if(mDown) {
if (mCubes.get(i).moveDown(feld)) {
mDown = false;
}
}
//mCubes.get(i).invalidate();
//mCubes.get(i).requestLayout();
mCubes.get(i).draw(mCanvas);
}
if(newCube)
addCube();
}
} finally {
if(mCanvas != null){
mSh.unlockCanvasAndPost(mCanvas);
}
}
}
}
public void addCube(){
Random r = new Random();
Cube cube = new Cube(mContext, mBuchstaben[r.nextInt(29)], r.nextInt(10), 0, mCanvas);
mCubes.add(cube);
}
}
This is my (shortened) fragment which uses the canvas/surface view:
public class KlassischFragment extends Fragment implements SurfaceHolder.Callback {
SurfaceHolder sh;
SurfaceView sv;
private CanvasThread thread;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_klassisch, container, false);
sv = (SurfaceView) view.findViewById(R.id.surfaceView);
sh = sv.getHolder();
sh.addCallback(this);
sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
return view;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread = new CanvasThread(sh, getContext());
thread.setRunnable(true);
thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
//thread.setRunnable(false);
while(retry){
try{
thread.join();
retry = false;
} catch(InterruptedException ie){
//Immer wieder versuchen
}
break;
}
thread = null;
}
}
Here is an example on how to draw a text on top of a square. Some of the values hardcoded but you should be able to make them dynamic.
public class Cube extends View {
private final static String TEST_STRING = "ABC";
private Paint mBackgroundPaint;
private Paint mTextPaint;
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public Cube(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public Cube(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public Cube(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public Cube(Context context) {
this(context, null, -1);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Just for demo purposes this should be calculated properly
int desiredWidth = 100;
int desiredHeight = 100;
setMeasuredDimension(desiredWidth, desiredHeight);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int savedCount = canvas.save();
drawRectangle(canvas);
drawText(canvas);
canvas.restoreToCount(savedCount);
}
private void init() {
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(Color.BLUE);
mBackgroundPaint.setStyle(Paint.Style.FILL);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
// This need to be adjusted based on the requirements that you have
mTextPaint.setTextSize(20.0f);
}
private void drawRectangle(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), mBackgroundPaint);
}
private void drawText(Canvas canvas) {
Rect rect = new Rect();
// For simplicity I am using a hardcoded string
mTextPaint.getTextBounds(TEST_STRING, 0, 1, rect);
int w = getWidth(), h = getHeight();
float x = (w - rect.width()) / 2, y = ((h - rect.height()) / 2) + rect.height();
canvas.drawText(TEST_STRING, 0, 1, x, y, mTextPaint);
}
}