등록일:2018-10-16 13:55:26 (0%) 작성자: 제목:How to draw an animated timer in Android
How to draw an animated timer in Android
Canvas drawing in Android can be an enormous topic to grasp, so setting yourself small achievable (albeit not practically useful) goals can be a great way to isolate things that you’re missing. This article will demonstrate how this can be done by drawing and animating a simple countdown timer.
Task
For the sake of clarity and simplicity, the task will be limited to drawing a colored arc that will start growing from 12 o’clock all the way around in a predefined timeframe. Below is a screenshot of the timer at around ⅔ of the way into this timeframe.
Solution
The solution will consist of preparing the custom view, drawing an arc and finally animating it.
Preparation
How you create your custom view is largely dependent upon how it integrates with the rest of the application, so I will keep this section intentionally vague. However, to see one possible working implementation, refer to the source code below under “Resources”.
We start with a new class that simply extends View. Because we will use an eraser to remove the inside diameter of the circle to make it an outline, the drawing needs to happen on a bitmap, which has a specific size. Hence, we create that bitmap (along with its canvas) in onSizeChanged() as follows:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (w != oldw || h != oldh) { mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); mBitmap.eraseColor(Color.TRANSPARENT); mCanvas = new Canvas(mBitmap); }
The rest may be unnecessary for your particular application, however the following trick is useful for any circular content if you want to ensure the view bounds are square regardless of the adjusted width:
defining the bounds for the inner and outer edges of the circle: and
applying both to make the image appear on screen.
First we define the paint for drawing the colored circle. How you want to set the color depends on your requirements, but it’s a good idea to supply that as an attribute.
mCirclePaint = new Paint(); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(circleColor);
Next comes the eraser paint, which, as its name suggests, erases the inside of the circle (that the first paint drew), leaving only an outline.
mEraserPaint = new Paint(); mEraserPaint.setAntiAlias(true); mEraserPaint.setColor(Color.TRANSPARENT); mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
The bounds will be defined in updateBounds() mentioned above in onSizeChange() as these will only change if the whole view is resized. All we need here is to define the rectangles for the outer and inner edges of the circle. These will be used by the circle paint and eraser paint, respectively.
Finally, we apply all of the above in onDraw(). Since we’re drawing on a bitmap, we will need to clear it from the previous frame first. Then we draw the arc and the erased inner circle onto the bitmap canvas; the sweeping angle defines how much of the circle is filled in (from 0 to 360 degrees). However, we cannot see the contents of the bitmap until it’s applied to the view canvas, which is done last.
Now that we can draw a static arc for any given sweeping angle, we need to animate that angle changing for the duration of the countdown timer.
To achieve this, we iterate between 0 and 1 with a ValueAnimator, which defines the progress fraction for the angle. A linear interpolator is used to ensure an even growth of the arc; other interpolators will give an inaccurate impression of the progress of our countdown.
The actual setup for each frame is trivial: we multiply the progress fraction by 360 degrees to get the sweeping angle for each frame and simply invalidate the view to invoke a new draw cycle.
Although the ultimate result of this exercise is a simple colored arc that grows into a circle, we’ve learned a few things that can be useful in real applications: drawing basic shapes, erasing parts of those shapes to create more complex shapes and finally working with timers and coordinates to create frame-by-frame animations of your drawings. Combining that knowledge with more exploration of the API can help achieve more impressive and practically useful results.