3

We have a problem to generate a bitmap from a particular view. The restriction is that it can not be rendered view (drawing). Does anyone have any tips how to solve this?

The documentation of the class view (http://developer.android.com/reference/android/view/View.html) has some explanation of the steps used by Android to render a View. In the case, we would get in step "layout", but not in the "drawing". Anyone who has any idea, could show an example?

My code is generating the exception: error -> width and height must be> 0

...
public static Bitmap loadBitmapFromView(View v) {
    Bitmap b = null;
    try {
        b = Bitmap.createBitmap(
                v.getWidth(),
                v.getHeight(), 
                Bitmap.Config.ARGB_8888);                
        Canvas c = new Canvas(b);
        v.measure(v.getWidth(), v.getHeight()); 
        v.layout(0, 0, v.getWidth(), v.getHeight());
        v.draw(c);

    } catch (Exception e) {

        Log.e(MainActivity.TAG, "error -> "+e.getMessage());
    }



    return b;
}


public void snap(View v) {


    LayoutInflater inflate = (LayoutInflater) getBaseContext()
            .getSystemService(LAYOUT_INFLATER_SERVICE);
    View view = new View(getBaseContext());
    view = inflate.inflate(R.layout.list_item, null);


    Log.d(MainActivity.TAG, "getWidth -> "+view.getWidth());
    Log.d(MainActivity.TAG, "getHeight   -> "+view.getHeight());

    Bitmap b = loadBitmapFromView(view);
    if (b != null) {

        LinearLayout mainLayout = (LinearLayout) findViewById(R.id.LinearLayout1);
        ImageView image = new ImageView(this);
        image.setImageBitmap(b);

        mainLayout.addView(image);
    }


}
Douglas Frari
  • 4,167
  • 2
  • 22
  • 23
  • I really didn't understand what you want to achieve. But the view will not have a size before the `onMeasure` step. So, just inflate the view will not do the trick. – Thiago Moura May 16 '13 at 23:21
  • Can you generate a bitmap from the a view without drawing it? I would like to generate an image (Bitmap) to a view that has not been drawn on the screen. The idea is to generate multiple bitmap images and show only when needed. – Douglas Frari May 17 '13 at 02:27

2 Answers2

10

I found the solution this way:

public static Bitmap getScreenViewBitmap(final View v) {
    v.setDrawingCacheEnabled(true);

    v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

    v.buildDrawingCache(true);
    Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false); // clear drawing cache

    return b;
}
Douglas Frari
  • 4,167
  • 2
  • 22
  • 23
1

You're immediately trying to get the width and height of the view after inflation, but the View doesn't have a size until after it's been laid out. You can either determine a size for it yourself (call measure() with whatever MeasureSpec is appropriate) or have it as part of a layout, set to Invisible, and only try to load the Bitmap from the View after it has been laid out.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • Hi kcoppock, your suggestion is like this discussion: http://stackoverflow.com/questions/4393612/when-can-i-first-measure-a-view ? – Douglas Frari May 17 '13 at 02:39
  • 1
    Right, you could add an onGlobalLayout listener, but then the view has to be part of a layout. Your steps should work, the problem is you can't rely on getWidth() and getHeight() at the current time. If you hardcoded values there, it should work. In that scenario, you'll either need to hardcode values, or measure the view yourself to get the proper dimensions for it. – Kevin Coppock May 17 '13 at 20:52