I want to develop a custom component which draws part of the circle based on different values. e.g draw 1/4 cirle, 1/2 circle etc. The component needs to be animated to display drawing process. The partial circle is drawn on top of a static imageview, and I plan to use two views, animated one on top of the static one. Any suggestion how to develop this?
I put the screenshot for reference.
Please refer to the picture, and get a feel how it looks like. Thanks!
Thanks in advance.
You have to draw the circle view, and after that you should create an animation to it.
Creating the circle view:
public class Circle extends View { private static final int START_ANGLE_POINT = 90; private final Paint paint; private final RectF rect; private float angle; public Circle(Context context, AttributeSet attrs) { super(context, attrs); final int strokeWidth = 40; paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(strokeWidth); //Circle color paint.setColor(Color.RED); //size 200x200 example rect = new RectF(strokeWidth, strokeWidth, 200 + strokeWidth, 200 + strokeWidth); //Initial Angle (optional, it can be zero) angle = 120; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint); } public float getAngle() { return angle; } public void setAngle(float angle) { this.angle = angle; } }
Creating the animation class to set the new angle:
public class CircleAngleAnimation extends Animation { private Circle circle; private float oldAngle; private float newAngle; public CircleAngleAnimation(Circle circle, int newAngle) { this.oldAngle = circle.getAngle(); this.newAngle = newAngle; this.circle = circle; } @Override protected void applyTransformation(float interpolatedTime, Transformation transformation) { float angle = oldAngle + ((newAngle - oldAngle) * interpolatedTime); circle.setAngle(angle); circle.requestLayout(); } }
Put circle into your layout:
<com.package.Circle android:id="@+id/circle" android:layout_width="300dp" android:layout_height="300dp" />
And finally starting the animation:
Circle circle = (Circle) findViewById(R.id.circle); CircleAngleAnimation animation = new CircleAngleAnimation(circle, 240); animation.setDuration(1000); circle.startAnimation(animation);
The result is:
As extra from @JohnCordeiro answer. I have added parameters from xml to reuse the circle and to fill the circle if needed.
class RecordingCircle(context: Context, attrs: AttributeSet) : View(context, attrs) { private val paint: Paint private val rect: RectF private val fillPaint: Paint private val fillRect: RectF var angle: Float var startAngle: Float init { val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordingCircle) startAngle = typedArray.getFloat(R.styleable.RecordingCircle_startAngle, 0f) val offsetAngle = typedArray.getFloat(R.styleable.RecordingCircle_offsetAngle, 0f) val color = typedArray.getColor(R.styleable.RecordingCircle_color, ResourcesCompat.getColor(resources, R.color.recording, null)) val strokeWidth = typedArray.getFloat(R.styleable.RecordingCircle_strokeWidth, 20f) val circleSize = typedArray.getDimension(R.styleable.RecordingCircle_cicleSize, 100f) val fillColor = typedArray.getColor(R.styleable.RecordingCircle_fillColor, 0) typedArray.recycle() paint = Paint().apply { setAntiAlias(true) setStyle(Paint.Style.STROKE) setStrokeWidth(strokeWidth) setColor(color) } rect = RectF( strokeWidth, strokeWidth, (circleSize - strokeWidth), (circleSize - strokeWidth) ) fillPaint = Paint().apply { setAntiAlias(true) setStyle(Paint.Style.FILL) setColor(fillColor) } val offsetFill = strokeWidth fillRect = RectF( offsetFill, offsetFill, (circleSize - offsetFill), (circleSize - offsetFill) ) //Initial Angle (optional, it can be zero) angle = offsetAngle } override protected fun onDraw(canvas: Canvas) { super.onDraw(canvas) if (fillColor > 0) { canvas.drawArc(rect, 0f, 360f, false, fillPaint) } canvas.drawArc(rect, startAngle, angle, false, paint) } }
And on the xml:
<com.myapp.RecordingCircle android:id="@+id/cameraRecordButton" android:layout_width="match_parent" android:layout_height="match_parent" app:offsetAngle="360" app:color="@color/light_grey" app:strokeWidth="10" app:cicleSize="@dimen/camera_record_button" app:fillColor="@color/recording_bg" /> <com.myapp.RecordingCircle android:id="@+id/progress" android:layout_width="match_parent" android:layout_height="match_parent" app:startAngle="270" app:color="@color/recording" app:strokeWidth="10" app:cicleSize="@dimen/camera_record_button" />
Here the result: Note the semi-transparent fill of the button
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With