0

I am programmatically creating a view which never gets drawn to the screen (the view isn't inflated from XML or set on screen during an onCreate). Instead, I want to create a bitmap of the view to use for an image. However, I cannot get a bitmap/a correct bitmap.

I have looked over the site and have used various questions such as here: Converting a view to Bitmap without displaying it in Android?. Initially, I used the following code:

public Bitmap loadBitmapFromView(View v)
{
    Bitmap bitmap = Bitmap.createBitmap(v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888); //v.getWidth() and v.getHeight() are 0 since view isn't drawn
    Canvas canvas = new Canvas(bitmap);
    v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height); //v.getMeasuredHeight() and v.getMeasuredWidth() are zero --- not sure why?
    v.draw(canvas);
    return bitmap;
}

This code created a bitmap but it was always empty and didn't have the view as an image. So then I tried the third answer down (by @Dwivedi Ji), posted for convenience:

private Bitmap getViewBitmap(View v) {
    v.clearFocus();
    v.setPressed(false);
    v.setDrawingCacheEnabled(true);

    boolean willNotCache = v.willNotCacheDrawing();
    v.setWillNotCacheDrawing(false);

    int color = v.getDrawingCacheBackgroundColor();
    v.setDrawingCacheBackgroundColor(0);

    if (color != 0) {
        v.destroyDrawingCache();
    }
    v.buildDrawingCache();
    Bitmap cacheBitmap = v.getDrawingCache(); //This was always null
    if (cacheBitmap == null) { 
        Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
        return null;
    }

    Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);

    // Restore the view
    v.destroyDrawingCache();
    v.setWillNotCacheDrawing(willNotCache);
    v.setDrawingCacheBackgroundColor(color);
    v.setDrawingCacheEnabled(false);

    return bitmap;
}

The v.getDrawingCache() call always returns null which left me without a bitmap.

How could I get this bitmap with the view image? I apologize for the lengthy question (kinda new to posting here, please let me know if you need additional info/clarification).

Thanks in advance!

EDIT

The class that I am try to make into a bitmap is as follows:

public class CircleView extends View
{
    ... //Constructors - Nothing special here

    @Override protected void onDraw(Canvas canvas)
    {
        canvas.drawColor(0x00000000);

        if(m_lineWidthPx == 0) //Previously set
            return;

        float centerX = getMeasuredHeight() / 2.f;
        float centerY = getMeasuredHeight() / 2.f;
        float radius = getMeasuredWidth() / 2.f - (m_lineWidthPx) / 2.f;
        m_paint.setStrokeWidth(m_lineWidthPx); //m_paint is instantiated in the constructors
        m_paint.setStyle(Paint.Style.STROKE);
        m_paint.setAntiAlias(true);
        canvas.drawCircle(centerX, centerY, radius, m_paint);
    }
}

There isn't very much to the class, basically draws a circle. I omitted the constructors since nothing special occurs there. They just set the m_lineWidthPx variable and instantiate the m_paint variable.

Community
  • 1
  • 1
V-PTR
  • 3,183
  • 3
  • 20
  • 21

3 Answers3

1

Check what size has your bitmap, isn't it 0x0 pt?

I use this approach to do this:

public static Bitmap getBitmapFromView(View view){

    view.measure(LinearLayout.LayoutParams.WRAP_CONTENT,
                 LinearLayout.LayoutParams.WRAP_CONTENT);

    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
                                        view.getHeight(),
                                        Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bitmap);
    view.draw(c);
    return bitmap;
}
Roman_D
  • 4,680
  • 2
  • 14
  • 17
  • Thank you, however, when I tried this the `getMeasuredWidth()/getMeasuredHeight()` and the `getWidth()/getHeight()` methods all return 0 – V-PTR Jul 13 '15 at 19:54
  • @PeteZa Could you provide the view which you try to convert in bitmap? – Roman_D Jul 14 '15 at 13:07
  • I updated my answer to include the class. Please let me know if you need anything else – V-PTR Jul 14 '15 at 13:38
  • Oh! Duh! The `onDraw` isn't ever getting called so the dynamic drawing that the class is for isn't being done! Thank you so much, I just need to basically do the drawing done in the onDraw to the canvas c in your answer. I'll try that and give an update! – V-PTR Jul 14 '15 at 13:45
1

I needed to create a bitmap from a View some time ago. After a lot of test/fail, I finally got working with this method:

public static Bitmap getBitmapFromView(View view) {
    view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
    view.draw(canvas);
    return bitmap;
}
Rafael Toledo
  • 5,599
  • 6
  • 23
  • 33
  • Thanks, but like with the answer from @RomanDonchenko the `getMeasuredWidth()/getMeasuredHeight()` methods return 0 – V-PTR Jul 13 '15 at 19:58
1

Thanks to both @Rafael Toledo and @Roman_Donchenko, I figured out the issue. The problem was that my custom view was doing the drawing in the onDraw method which doesn't get called. In my case, I simply needed to perform the drawing done in the onDraw directly to the canvas and then used the bitmap passed to the canvas. My code ended up being:

public Bitmap getBitmapFromCircleView(CircleView v)
{
    Bitmap bitmap = Bitmap.createBitmap(v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    v.drawToCanvas(canvas); //Method in the custom CircleView class, posted below
    return bitmap;
}

public class CircleView extends View
{
    ... //Constructors

    public Canvas drawToCanvas(Canvas canvas)
    {
        canvas.drawColor(0x00000000);

        if(m_lineWidthPx == 0) //Previously set
            return null;

        int width = getLayoutParams().width;
        int height = getLayoutParams().height;

        float centerX = height / 2.f;
        float centerY = height / 2.f;
        float radius = width / 2.f - (m_lineWidthPx) / 2.f;
        m_paint.setStrokeWidth(m_lineWidthPx); 
        m_paint.setStyle(Paint.Style.STROKE);
        m_paint.setAntiAlias(true);
        canvas.drawCircle(centerX, centerY, radius, m_paint);
        return canvas;
    }

    @Override protected void onDraw(Canvas c)
    {
        ... //Code here remained unchanged
    }
}
V-PTR
  • 3,183
  • 3
  • 20
  • 21