Canvas : The Real Play Ground! Android

Saurabh Pant
AndroidPub
Published in
4 min readOct 29, 2017

--

If it is a need, Create it and take charge!

When it comes to create something which is not available on the layout.xml as native component, developers face real challenge. When drawables are not enough and styles are not sufficient, what we left with is the option of Drawing it!

Canvas — the real play ground wherein a developer can create any type of view or animation. But there is a hesitation in opting for it because it seems a bit complicated but actually it is not. So let’s dive into the world of Canvas.

Clock drawn on Canvas

Exactly! We’re going to create a running clock with seconds and minutes ticker. Why Clock? Well! because it requires

  1. Use of lines, circles, arcs and text (which are enough to tackle at once)
  2. A continuous pulse for its operation (without disturbing the main thread)
  3. Use of geometry. (Remember cos, sin and tangent)
  4. It also presents a challenge to keep its drawing clean and simple.
  5. Lastly, its a bit complicated! Yes.

So Firstly, how Canvas works? Let’s take a look on some of the important methods which we generally need and they are

@Override
protected void onDraw(Canvas canvas) {}

This is the place where all the adventure happens. Whatever we need to draw, will fall in this method. Because it is drawing, we continuously refreshes it. So, we must avoid creating objects in it and also try to keep calculations outside it as much as possible. Hence, whenever we make a change in the view or updates it, it should be reflected and for that we need to redraw it again.

invalidate();

Canvas is a blank slate, so whenever we make a change in the view or updates it, it should be reflected and for that we need to redraw it again and we call invalidate().

@Override
protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) { setMeasuredDimension(finalWidth, finalHeight); }

How we want to set our view on the screen depending on the width and height provided by the parent, we can set it in the onMeasure(). We must call setMeasuredDimension() in the end so as to provide our own size to the view.

Now, let’s take a look at how we’re going to create our clock base.

Clock behind the scene

Our ClockView has mainly 6 components and they are ClockCover and ClockCenter, Intervals and their text, Seconds and Minutes Ticker. We’ve to redraw them continuously to keep the clock ticking. We’ll keep any calculations away from our onDraw() so that refresh rate would be faster.

how our onDraw() looks like

We also require some geometrical calculations to maintain the ticking angles of seconds and minutes. We’ve mentioned all our such constants in ClockConstants.java.

Clock Constants and Geometry

We also sets our view size as one third of the available screen width and making it a square.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
finalWidth = getMeasuredWidth() / 3;
finalHeight = getMeasuredWidth() / 3;
mRadius = (finalWidth / 2);
setMeasuredDimension(finalWidth, finalHeight );
}

Now comes is the pulsation part for our clock. Here we’re using multi threading to avoid any blockage on the main thread. We create a TickerThread.java which maintains the pulse of 1 second and notify us via the Handler on the main thread. Finally, in the main thread, we calculate the next angle of rotation for both seconds and minutes ticker and invalidate() our view and our clock keep moving.

when everytime clock has to move, tick() called

On each tick, clock calculates toRotationAngle for the seconds ticker and also maintains the fromRotationAngle which is its previous state. Now we loop through each value of angle between to and from rotation and move our seconds and minutes ticker.

setting the minutes and seconds ticker coordinate

Each time ticker moves an angle, we calculate the coordinate for both tickers and redraw them on the view. We also have to initialize the starting points of all the components in the beginning. This way it seems that the clock is ticking continuously.

That’s it! See it is simple!

You can deep dive into the code here and check out details there.

If you like it or it help you in understanding, please star it and share.

Hope it helps you someway in creating your own views.

Happy Drawing!! :)

--

--

Saurabh Pant
AndroidPub

App Developer (Native & Flutter) | Mentor | Writer | Youtuber @_zaqua | Traveller | Content Author & Course Instructor @Droidcon | Frontend Lead @MahilaMoney