Android: Drawing a canvas to an ImageView

101,471

Solution 1

I had the same challenge and came to the conclusion that overwriting onDraw will at least in the general case not work. My blog explains the reasons. What worked very well for me is the following:

  1. Create a new image bitmap and attach a brand new canvas to it.
  2. Draw the image bitmap into the canvas.
  3. Draw everything else you want into the canvas.
  4. Attach the canvas to the ImageView.

Here is a code snippet for this:

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));

Solution 2

     ImageView imageView=(ImageView) findViewById(R.id.image);
        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);    
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);
        canvas.drawCircle(50, 50, 10, paint);
        imageView.setImageBitmap(bitmap);

Solution 3

I think that a better approach would be to create a custom ImageView and Override the onDraw method. Something like:

public class CustomView extends ImageView {

public CustomView(Context context) {
    super(context);
}

public CustomView(Context context, AttributeSet attrst) {
    super(context, attrst);
}

public CustomView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

MyBitmapFactory bitMapFac = null;
public void setBitmapFactory(MyBitmapFactory bitMapFac)
{
    this.bitMapFac = bitMapFac;
}

@Override
public void onDraw(Canvas canvas) {

    canvas.drawColor(Color.TRANSPARENT);
    /*instantiate a bitmap and draw stuff here, it could well be another
    class which you systematically update via a different thread so that you can get a fresh updated
    bitmap from, that you desire to be updated onto the custom ImageView. 
   That will happen everytime onDraw has received a call i.e. something like:*/
    Bitmap myBitmap = bitMapFac.update(); //where update returns the most up  to date Bitmap
    //here you set the rectangles in which you want to draw the bitmap and pass the bitmap        
    canvas.drawBitmap(myBitMap, new Rect(0,0,400,400), new Rect(0,0,240,135) , null);
    super.onDraw(canvas);
    //you need to call postInvalidate so that the system knows that it  should redraw your custom ImageView
    this.postInvalidate();
}
}

It would be a good idea to implement some logic that checks if there is a fresh bitmap to acquire via the update() method, so that the code inside onDraw won't execute every time and put overhead to the system.

And then use your custom view wherever you need it. The easiest way would be to declare it directly inside the activity_layout.xml as such:

   <com.mycustomviews.CustomView
        android:id="@+id/customView"
        android:layout_centerInParent="true"
        android:layout_height="135dp"
        android:layout_width="240dp"
       android:background="@android:color/transparent"/>

And then access is in your code like any other view by using:

   customView = (CustomView) findViewById(R.id.customView);
Share:
101,471
Admin
Author by

Admin

Updated on September 16, 2020

Comments

  • Admin
    Admin over 3 years

    I'm new to android programming and what I'm trying to figure out is this;

    In my layout i have a TextView, ImageView, and Button, all on a vertically oriented LinearLayout.

    I want to be able to dynamically draw circles in the ImageView, without disturbing the rest of my layout(textview/button). I'm trying to create a canvas, and use the drawcircle function within canvas to set the location of the circle. And then draw that canvas to my imageview in some way. I cannot get this to work, is there a trick to this? Or is my method fundamentally wrong? How would i go about drawing circles to the ImageView without recreating my entire layout?

    Thanks!

  • balachandarkm
    balachandarkm over 9 years
    Just a suggestion as I came across the same issue, Instead of creating a new BitmapDrawable, We can utilize myImageView.setImageBitmap(tempBitmap) function as well!
  • Rosario Vivas
    Rosario Vivas about 8 years
    and what if I wanna delete canvas after setImageBitmap?