Drawing on top of an image in Android’s ImageView

This is a topic for which I found on the Internet a lot of ideas but they were more workarounds for special situations than general solutions.

One of my apps contained an ImageView widget into which I had to load a series of pictures one after the other at runtime. The pictures were of different size, some smaller and some larger than the widget’s size, so the images would either be centered or automatically scaled down by the widget. The challenge was to mark certain areas in the picture with a coloured rectangle dynamically created at run time and adjusted using the coordinates of the original, unscaled image.

The general recommendation on the Internet was to subclass ImageView and overwrite OnDraw with a method that first calls the original OnDraw method of ImageView with the canvas that is provided as parameter to OnDraw and then draws into this canvas on top of the already drawn image.

I am meanwhile quite sure that this works only under certain circumstances, for example when you are sure, your image will not be scaled. The problem lies in the provided canvas. The original onDraw method applies a certain transformation matrix to the canvas before it draws the image into the canvas and restores the canvas in its previous state afterwards. This matrix is stored in a private member variable of ImageView and for whatever reason it is not always the same matrix as the one returned from getImageMatrix() calls. Using the debugger I have seen cases where getImageMatrix returned a non-null matrix where onDraw used a null Matrix and therefore did no do any transformation to the canvas at all. So there is no general reliable way to calculate the coordinates for anything you want to draw on top of what ImageView has drawn.

Therefore I used a different approach:

  1. Create a new image bitmap and attach a brand new canvas to it so that the bitmap and the canvas use the same coordinate system.
  2. Draw the image bitmap into the canvas.
  3. Draw everything else you want into the canvas (the rectangles in my case).
  4. Attach the canvas to the ImageView.

Here is the code snippet:

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;

ImageView myImageView = ...
Bitmap myBitmap = ...
Paint myRectPaint = ...
int x1 = ...
int y1 = ...
int x2 = ...
int y2 = ...

//Create a new image bitmap and attach a brand new canvas to it
Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);

//Draw the image bitmap into the cavas
tempCanvas.drawBitmap(myBitmap, 0, 0, null);

//Draw everything else you want into the canvas, in this example a rectangle with rounded edges
tempCanvas.drawRoundRect(new RectF(x1,y1,x2,y2), 2, 2, myPaint);

//Attach the canvas to the ImageView
myImageView.setImageDrawable(new BitmapDrawable(getResources(), tempBitmap));

Warning: count(): Parameter must be an array or an object that implements Countable in /homepages/38/d73375733/htdocs/wordpress/wp-includes/class-wp-comment-query.php on line 405

9 thoughts on “Drawing on top of an image in Android’s ImageView

  1. My code snippet shows you the main “ingredients” for your activity: An ImageView, a Canvas and a Bitmap.

    Create an ImageView for your activity the usual way, there is plenty of sample code for this available on the internet.

    What you then have to do is to load the picture from the SD Card into a Bitmap (BitmapFactory.decodeFile does this for you) and then use my code snippet to create a new Canvas, draw the Bitmap and your circles into the Canvas and attach the canvas to your ImageView.

    Think of the canvas as a piece of paper on which you can make a drawing by painting bitmaps, lines, circles etc. on it. As soon as you have attached the Canvas to the ImageView the drawing of the paper appears within the ImageView.

    I hope this helps a bit.


  2. sir i am working on a project in which i am drawing diff. shapes like rect,oval
    in canvas for which i have a class which extends view.
    problem is that i want to draw over an image but dont know how to merge image in the class which extends view..
    please help me

  3. You actually attach tempBitmap and not tempCanvas to the ImageView. Your comments however say, that you attach the canvas to the ImageView.

  4. thanks for your code , i worked on project to draw points over image just i want to know what i put in myBitmap declare ?
    i assign it to null and code not working

  5. Great , very helping.
    I just want to know if I am drawing a number of the rectangle on my image view. How do I get click events on those rectangles?

  6. Hi I just want to say I was tearing my hair out for days trying to figure out how to make a very small bitmap playing card image, loaded by ID from a resource .PNG file, draw onto an ImageView that was created on my activity layout. It seemed like nothing on earth would make it display. After going down some very complicated rabbit holes, your simple and elegant code above did the job. I can’t praise the solution enough, thank you!

  7. I changed the last line of your snippet to


    and it worked perfectly, thank you for your help

Leave a Reply

Your email address will not be published. Required fields are marked *