The curious case of Android Canvas

Ninad MG
ProAndroidDev
Published in
2 min readMar 17, 2018

--

Anyone who has worked with the android custom views will be familiar with the onDraw method. This is where we draw the view to the android canvas to be shown on the screen.

We had to create a view which would rotate corresponding to a given viewRotation value. So my on draw method looked like this.

override fun draw(canvas: Canvas?) {

canvas?.rotate(viewRotation, (canvas.width/2).toFloat(), (canvas.height/2).toFloat())

super.draw(canvas)
}

Here the canvas is rotated with its centre as the pivot point. Everything works fine. The view is rotated and drawn to the screen according to the specified viewRotation value.

The view looks fine with the rotation.

Everything looked fine till we wanted to get a screen shot of the layout.

Bitmap.createScaledBitmap(v.drawingCache, width, height, false)

Screenshot looked entirely different; our view was clipped and the position was entirely different than what we expected.

The bitmap imaged generated.

After generously sprinkling Log.d calls in code base something caught our eye. When we logged the canvas height and width.

Log.d(TAG,"width -> ${canvas.width} , height -> ${canvas.height}")

The logs showed when the layout was used the canvas height and width was the same as the view height and width.

width -> 1008 , height -> 768

But when we try to take the screen shot the canvas returned the height and width as screen height and width .

width -> 1340 , height -> 2048

This is why the bitmap clipped the view was turning with the wrong pivot point. The issue was fixed by taking the view height and width instead of the the canvas height and width. The final code is

canvas?.rotate(viewRotation, (width/2).toFloat(), (height/2).toFloat())

This works perfectly. Why the canvas height and width are inconsistent needs to be checked. But that is for another day.

--

--