将视图转换为位图而不在Android中显示它?

sun*_*nil 123 android bitmap

我将尝试解释我到底需要做什么.

我有3个独立的屏幕,分别是A,B,C.还有另一个名为HomeScreen的屏幕,其中所有3个屏幕位图都应显示在图库视图中,用户可以选择他想去哪个视图.

通过将所有代码仅放在HomeScreen Activity中,我已经能够获得所有3个屏幕的位图并将其显示在Gallery视图中.现在,这使代码变得很复杂,我想简化它.

那么,我可以从HomeScreen调用另一个Activity并且不显示它,只是获取该屏幕的Bitmap.例如,假设我只调用HomeScreen,它调用活动A,B,C,并且不会显示A,B,C中的任何活动.它只是通过getDrawingCache()给出该屏幕的Bitmap.然后我们可以在HomeScreen的Gallery视图中显示这些位图.

我希望我已经非常清楚地解释了这个问题.

如果这确实可行,请告诉我.

Sim*_*mon 200

有办法做到这一点.你必须创建一个Bitmap和一个Canvas并调用view.draw(canvas);

这是代码:

public static Bitmap loadBitmapFromView(View v) {
    Bitmap b = Bitmap.createBitmap( v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);                
    Canvas c = new Canvas(b);
    v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
    v.draw(c);
    return b;
}
Run Code Online (Sandbox Code Playgroud)

如果视图在其大小为零之前未显示.可以像这样测量它:

if (v.getMeasuredHeight() <= 0) {
    v.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    Bitmap b = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    v.draw(c);
    return b;
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据这篇文章,传递WRAP_CONTENT作为值makeMeasureSpec()不做任何好事(虽然对于一些视图类它确实有效),推荐的方法是:

// Either this
int specWidth = MeasureSpec.makeMeasureSpec(parentWidth, MeasureSpec.AT_MOST);
// Or this
int specWidth = MeasureSpec.makeMeasureSpec(0 /* any */, MeasureSpec.UNSPECIFIED);
view.measure(specWidth, specWidth);
int questionWidth = view.getMeasuredWidth();
Run Code Online (Sandbox Code Playgroud)

  • `Bitmap b = Bitmap.createBitmap(v.getWidth(),v.getHeight(),Bitmap.Config.ARGB_8888);`效果更好 (6认同)
  • 我实际上必须将其更改为`v.layout(v.getLeft(),v.getTop(),v.getRight(),v.getBottom());`以使其正常工作,但感谢代码:) (4认同)
  • 我必须使用v.getWidth()而不是v.getLayoutParams().width和类似的高度.否则,现在正在工作. (3认同)

Gil*_* SH 26

这是我的解决方案:

public static Bitmap getBitmapFromView(View view) {
    Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(returnedBitmap);
    Drawable bgDrawable =view.getBackground();
    if (bgDrawable!=null) 
        bgDrawable.draw(canvas);
    else 
        canvas.drawColor(Color.WHITE);
    view.draw(canvas);
    return returnedBitmap;
}
Run Code Online (Sandbox Code Playgroud)

请享用 :)


Dwi*_* Ji 20

试试这个,

        /**
         * Draw the view into a bitmap.
         */
        public static Bitmap getViewBitmap(View v) {
            v.clearFocus();
            v.setPressed(false);

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

            // Reset the drawing cache background color to fully transparent
            // for the duration of this operation
            int color = v.getDrawingCacheBackgroundColor();
            v.setDrawingCacheBackgroundColor(0);

            if (color != 0) {
                v.destroyDrawingCache();
            }
            v.buildDrawingCache();
            Bitmap cacheBitmap = v.getDrawingCache();
            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);

            return bitmap;
        }
Run Code Online (Sandbox Code Playgroud)


a.c*_*ch. 17

Android KTX 中有一个很棒的 Kotlin 扩展功能: View.drawToBitmap(Bitmap.Config)

  • 如果视图未在布局中呈现,这将不起作用。错误:“IllegalStateException:需要在调用 drawToBitmap() 之前布置视图” (11认同)

lev*_*ker 16

我知道这可能是一个陈旧的问题,但我遇到了让这些解决方案适合我的问题.具体来说,我发现如果在视图被夸大之后对视图进行了任何更改,那么这些更改将不会合并到渲染的位图中.

这是最终为我的案例工作的方法.然而,有一点需要注意.在打电话之前,getViewBitmap(View)我夸大了我的观点并要求它以已知尺寸进行布局.这是必需的,因为我的视图布局将使其高度/宽度为零,直到内容被放入其中.

View view = LayoutInflater.from(context).inflate(layoutID, null);
//Do some stuff to the view, like add an ImageView, etc.
view.layout(0, 0, width, height);

Bitmap getViewBitmap(View view)
{
    //Get the dimensions of the view so we can re-layout the view at its current size
    //and create a bitmap of the same size 
    int width = view.getWidth();
    int height = view.getHeight();

    int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
    int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);

    //Cause the view to re-layout
    view.measure(measuredWidth, measuredHeight);
    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

    //Create a bitmap backed Canvas to draw the view into
    Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);

    //Now that the view is laid out and we have a canvas, ask the view to draw itself into the canvas
    view.draw(c);

    return b;
}
Run Code Online (Sandbox Code Playgroud)

我的"神奇酱"在这里找到:https: //groups.google.com/forum/#!topic/android-Developers/BxIBAOeTA1Q

干杯,

列维


Shy*_*mar 5

位图布局或视图:

 private Bitmap createBitmapFromLayout(View tv) {      
    int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    tv.measure(spec, spec);
    tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
    Bitmap b = Bitmap.createBitmap(tv.getMeasuredWidth(), tv.getMeasuredWidth(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.translate((-tv.getScrollX()), (-tv.getScrollY()));
    tv.draw(c);
    return b;
}
Run Code Online (Sandbox Code Playgroud)

调用方法:

Bitmap src = createBitmapFromLayout(View.inflate(this, R.layout.sample, null)/* or pass your view object*/);
Run Code Online (Sandbox Code Playgroud)