Learning Custom Views in Android
I just created my first custom view, and I would like to share what I learned and hopefully this can help someone to create their own custom view. Basically, this custom view is simple analog clock view, where we can put in our xml then it will just work. Here is the screenshot
It’s available in github and everyone can use this as library
Let’s see the components I used to create the view.
This is a way to draw an arc. We can draw complete circle with this method. From the documentation we can see this
In an circle we have angle, so startAngle is starting point to draw the arc. SweepAngle is the how long the arc will be. The zero in startAngle starts from 3 o'clock, so if we put -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, to draw a circle we will need to have a square as rectF which has 4 equal sides.
1 2 3 4 5 6 7 8 9
We create a rectF with size 400 in all 4 sides, then draw an arc inside of this
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 to draw rounded rect to point to 5 o'clock? This is where
Canvas.rotate() come to play.
We basically save the snapshot of the current canvas with
Canvas.save(). I would say this thing saves the position of each view inside of the canvas. First we draw the rounded rectangular to 12 o'clock, then rotate the canvas 150 degrees to get it to 5 o'clock. (every hour is 30 degrees)
Canvas.restore to restore position of each view from last save. it won’t restore the rounded rect because we save before we draw this.
3. Touch Area and Selected Area
This is one the hardest part in this custom view. This is about how to make our custom view clickable and respond to our touch.
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