Learning Custom Views in Android
Today, I would like to share my experience with custom views, and hopefully this can help someone to create their own custom view. The custom view here is a simple analog clock, it’s analog clock view where we can put it in xml to show it. Here is the sample
It’s available in github and everyone can take a look
Let’s see how I created this custom view
Canvas.drawArc() is a function from Canvas API. The basic functionality of this api is to draw arc and we can use this to draw complete circle.
Basically, the startAngle is starting point to draw the arc which starts from 3 o'clock and sweepAngle is how long the arc will be so if we set -90 as startAngle, and 180 as sweepAngle, then android will draw half oval from 12 o'clock to 6 o'clock.
So, what is RectF in this case? It’s like the canvas where we want to draw the circle. The arc will follow the form of this rectF, so to draw a circle we need the canvas to be a square which has 4 equal sides.
1 2 3 4 5 6 7 8 9
In the code above, we create a rectF and set the size to be 400 in all 4 sides, then we can draw an arc inside of this rectF
2. Draw Moving Hands in Analog Clock
We have moving hands in the analog clock for hour, minute, and second. How to draw this? Basically the hands are just rectangular with rounded corners. We can draw rounded rectangular easily with
Canvas.drawRoundRect() api but how do we draw rounded rect to point to 5 o'clock? This is where
Canvas.rotate() come to play.
First we save the snapshot of the current canvas with
Canvas.save(). I would say this saves the position of each view inside of the current canvas.
Second we draw the rounded rectangular to point to 12 o'clock, then rotate the canvas 150 degrees to get it to 5 o'clock. (every hour is 30 degree)
Canvas.restore to restore position of each view from last save. it won’t restore the position of rounded rectangle and its rotation because we call ‘Canvas.save’ before we draw these
3. Touch Area and Selected Area
This is one the hardest part in this custom view. It’s about how to make our custom view clickable and give feedback to our touches.
So, how do we define touch area for specific view? By using Region. Defining a region is basically the same like we draw a view. We can use the arc as the region, but we should make the region in such way that the user can easily touch and select the item.
That’s why we need
Path instead of only an arc, because with
Path we can define the touch area we want instead of just an arc.
Look on the screenshot for custom view again, we want to make sure that user can easily select the data. So we are going to make touch area from the center of the view to arc. It’s like slice of pizza. Here is to give you picture.
The slices with grey background are the touch area, so whenever user touches inside of this area, the item will be selected.
Remember, in order to define touch area, we need to know how to draw it. Let’s see how we can define this area.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
First, we are going to define the first arc which is the curve of the slice, and then define the second arc, but if you look closely, the rect for second arc is the center of the view which is height and width of the canvas divided by 2. So there is actually no arc. It’s just telling path to use this center view.
Path.close() will close those 2 arcs with lines. That’s how we get the slice of the pie.
That’s it. we get the
Path and then we only need to set this path as region, and put it inside of the data list.
onTouchEvent() then we check whether the touch point is inside of one of the regions, then call sliceClickListener callback then call postInvalidate() to draw the selected area.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30