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);
Related
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.
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.
I'm trying to add a gradient only to Circle, but it gos out of circle. How can I fix this? Thanks in advance.
circlePaint.setShader(new RadialGradient(getWidth() / 2, getHeight() / 2, getHeight() / 5, 0xff000000,Color.TRANSPARENT, Shader.TileMode.CLAMP));
canvas.drawCircle(viewWidthHalf, viewHeightHalf, radius, circlePaint);
And by the way everything white behind layer with circle, insted of TRANSPARENT. Why it so?
I am using the sample second, hour, and minute ticker/clock hands for a sample watch face on Android Studio. There, draw line method of Canvas class is being used with a startX, startY, stopX, and stopY. My question is how do I implement this similarly using a picture? I thought of using drawBitmap which only has a left and top and so it rotates but way too widely and not in place as the hands do.
Is there any way to use an image instead of a line like in the drawLine method? The bottom line is that I need to use an image instead of a line as a clock hand.
Thanks!
You should use Canvas.save, Canvas.rotate and Canvas.restore. Imagine, that you always draw things in the same place, but the underlying canvas is being rotated, so you will draw in the right place. Consider the example from the Santa Tracker:
for (int i = 0; i < mCloudBitmaps.length; i++) {
canvas.save();
canvas.rotate(mCloudDegrees[i], centerX, centerY);
float r = centerX - (timeElapsed / (mCloudSpeeds[i])) % centerX;
mCloudFilterPaints[i].setAlpha((int) (r / centerX * 255));
canvas.drawBitmap(mCloudBitmaps[i], centerX, centerY - r,
mCloudFilterPaints[i]);
canvas.restore();
}
It doesn't draw hands, but instead the clouds on the watch face, but it should give you an example of what you need to try to do.
I'm drawing a custom shape using the path method, but it performs differently than is displayed.
As displayed in the Layout:
On the device:
This only happens when the angle at the left vertex becomes too small. If I widened the shape, such that it became a regular diamond, the entire shape appears (regardless of size).
Here's the code:
final Path p = new Path();
p.moveTo(x, y);
p.lineTo(x - height / 16, y - 20);
p.lineTo(x - width / 3, y);
p.lineTo(x - height / 16, y + 20);
p.close();
canvas.drawPath(p, mThumbColorPaint);
Can anyone enlighten me?