Android canvas draws curved semicircle - android

I want to draw smooth semicircle with drawArc() method. But what I get is:
RectF oval = new RectF(x - cornerRadius, y - cornerRadius, x + cornerRadius,y + cornerRadius);
canvas.drawArc(oval, start, 180, true, cornerPaint);
What's wrong with my code?

The problem has gone after I have created Paint from zero, not copying it from another Paint. Seems like another paint had parameters that affected line shape.

Related

Kotlin draw linear gradient relative to shape

I have a Paint object that contains a linear gradient like this:
init{
this.myPaint.shader = LinearGradient(0f, 0f, 0f, 15f, 0xFF1F9928.toInt(), 0xFF184F1E.toInt(), Shader.TileMode.MIRROR);
}
And i use it to draw a health bar for my character like this:
canvas.drawRect(x, y, x + 100f * fill, y + 15f, this.myPaint)
This work well. But when the character moves with the camera the gradient stays at its original place. This results in the health bar changing color based on its position.
How can i make the gradient stay fixed to the health bar, instead of the global coordinate system?
Never used LinearGradient myself however from what I can tell from the documentation. You will have to configure the shader every time you call drawRect. The gradient stays in the initial position because the gradient's coordinates never change.
Changes needed:
// pass appropriately the coordinates you want here
this.myPaint.shader = LinearGradient(0f, 0f, 0f, 15f, 0xFF1F9928.toInt(), 0xFF184F1E.toInt(), Shader.TileMode.MIRROR);
canvas.drawRect(x, y, x + 100f * fill, y + 15f, this.myPaint)
Be careful about creating object creation onDraw.
I found a solution.
You have to translate the canvas, and draw your gradient at (0, 0) position. Then restore the canvas back.
canvas.save()
canvas.translate(x, y)
canvas.drawRect(0, 0, 100f * fill, 15f, this.myPaint)
canvas.restore()
This is the correct way to do it.

Android: CustomView Circle Stroke not smooth

I have following code in my onDraw method:
canvas.drawArc(rect, -90, 360, true, bgpaint);
if(isFocussed)
canvas.drawArc(rect, -90, 360, true, strokePaint);
for strokePaint, this is what I have in my init() method:
strokePaint = new Paint();
strokePaint.setColor(Color.YELLOW);
strokePaint.setAntiAlias(true);
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setStrokeWidth(2);
Whenever the strokePaint comes into play, the circular stroke is not smooth. The stroke is flat by little bit at top, bottom, left and right.
How do I fix this problem?
Screenshot of the problematic circle:
You have to take the stroke width in account when drawing.
Just make your shape smaller about half of it.
Though I can't say it for sure depending on your code, I just think that you are drawing outside of bounds of your view. That's a common issue.
Try with this setAntiAlias(true)and setStrokeCap(Paint.Cap.ROUND)

Setting a radial gradient as the background color of a circle on canvas

I draw some circles on a canvas using .drawCircle.
I would like the fill color of that circle to be a radial gradient (or linear gradient if that's not possible).
Basically I want the circles to have some depth to them.
I'm not quite sure how to accomplish this.
I know I can define a gradient as a drawable, but is there a way to set that as the background for the drawn circle?
For example in WPF I can simply define a LinearGradientBrush and define it's stop points.
Some code for context:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(4);
canvas.drawCircle((float) temp_dot.get_x(),
(float) temp_dot.get_y(),
(float) temp_dot.get_radius(),
paint);
Thanks in advance for your time.
before drawing the circle, use the following code :
paint.setShader(new RadialGradient(
centerX,
centerY,
radius,
centerColor,
externalColor,
Shader.TileMode.CLAMP
));
canvas.drawCircle(..., paint);
See the RadialGradient if you want to have a more custom radial gradient.

Weird behaviour in drawing a ring using Path.arcTo() in Android

I have implemented an animated drawing ring by start sweeping at angle 0 to 360 successfully.
However when the tail of the ring meets its head at 360 angle, all drawing is disappear.
This is my code for the ring in onDraw()
float startAngle = 270;
float sweepAngle = -359;
paint.setColor(Color.DKGRAY);
paint.setShadowLayer(4, 2, 2, 0x80000000);
rectF.set(cenX - outerRadius, cenY - outerRadius, cenX + outerRadius,
cenY + outerRadius);
path.arcTo(rectF, startAngle, sweepAngle);
//canvas.drawArc(rectF, 0, 360, false, paint);
rectF.set(cenX - innerRadius, cenY - innerRadius, cenX + innerRadius,
cenY + innerRadius);
/*paint.reset();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
canvas.drawArc(rectF, 0, 360, false, paint);*/
path.arcTo(rectF, startAngle + sweepAngle, -(sweepAngle));
canvas.drawPath(path, paint);
and this is the result,
notice here that i set sweepAngle to -359 just before it becomes circle.
However if I change sweepAngle to -360. It produces this result.
It disappears!!
Anyone know how to solve this please help me?
Thanks.
PS. I don't want to use drawArc() because I want to make a hole inside the ring. With drawArc(), my button will be gone.
I suppose android will mod 360 before really drawing it. So x - 360 === x and it will draw nothing!
I'm way late with this, but I solved it by adding a solid circle as the last frame of the animation (I was using AnimationDrawable, but the idea is the same in this case). All the draw code was the same for that last frame, except one line:
replace:
mPath.arcTo(rectF, startAngle, sweepAngle);
with something like:
mPath.addCircle(cenX, cenY, innerRadius, Path.Direction.CCW);

Circular sector shaped clipping mask with Path.addArc?

I need to create a clipping mask with a shape of a circular sector.
I am able to draw one using the following:
paint.setColor(0x88FF0000);
paint.setStyle(Style.FILL);
canvas.drawArc(oval, 0, 30, true, paint);
I want to use it as a clipping path, so I've tried:
Path path = new Path();
path.addArc(oval, 0, 30);
canvas.clipPath(path, Op.REPLACE);
However addArc doesn't have the useCenter parameter so what I get is not a sector but a segment.
Ok, it seems there is no proper way doing this using a clipping mask.
However there is an alternate way using PorterDuffXfermode. See Xfermodes in ApiDemos.
I simply draw a sector using drawArc over my image with the DST_OUT operator. This makes the part of the image covered by the sector invisible (not drawn).
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(0xFFFFFFFF);
paint.setStyle(Style.FILL);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
drawable.draw(canvas);
canvas.drawArc(oval, 30, 90, true, paint);
I needed to tweak the AChartEngine library for Android to turn the pie chart into a donut chart. I needed to replace the following:
canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
by using the Path class in order to be able to use clipping. The following code did the job for me:
Path path = new Path();
path.moveTo(oval.centerX(), oval.centerY());
path.addArc(oval, startAngle, sweepAngle);
path.lineTo(oval.centerX(), oval.centerY());
canvas.drawPath(path, paint);
I hope this saves some headaches to people not familiar with the Canvas API as myself.

Categories

Resources