在Android上将视图转换为位图

71

我需要将一个视图转换为位图以预览我的视图并将其保存为图像。我尝试使用以下代码,但它创建了一张空白图片。我无法理解我犯了哪个错误。

 View viewToBeConverted;  Bitmap viewBitmap =   Bitmap.createBitmap(viewToBeConverted.getWidth(), viewToBeConverted.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(viewBitmap); 
 viewToBeConverted.draw(canvas); 
 savephoto(“f1”, viewBitmap); 

 ////  public void savephoto(String filename,Bitmap bit)     
   {  
            File newFile = new File(Environment.getExternalStorageDirectory() + Picture_Card/"+ filename+ ".PNG");
              try 
{
                    newFile.createNewFile();                   
 try
 { 
                         FileOutputStream pdfFile = new FileOutputStream(newFile);                                                Bitmap bm = bit;                          ByteArrayOutputStream baos = new ByteArrayOutputStream();                          bm.compress(Bitmap.CompressFormat.PNG,100, baos);                                                     byte[] bytes = baos.toByteArray();                         
 pdfFile.write(bytes);                                              
      pdfFile.close();                   
 }
 catch (FileNotFoundException e) 
{                          //       

  }            
  } catch (IOException e)
 {                    //          
    }      
  }  
9个回答

163

这是我的解决方案:

  public static Bitmap getBitmapFromView(View view) {
        //Define a bitmap with the same size as the view
        Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
        //Bind a canvas to it
        Canvas canvas = new Canvas(returnedBitmap);
        //Get the view's background
        Drawable bgDrawable =view.getBackground();
        if (bgDrawable!=null) 
            //has background drawable, then draw it on the canvas
            bgDrawable.draw(canvas);
        else 
            //does not have background drawable, then draw white background on the canvas
            canvas.drawColor(Color.WHITE);
        // draw the view on the canvas
        view.draw(canvas);
        //return the bitmap
        return returnedBitmap;
    }

享受吧 :)


@Gil SH,你觉得最终图片的质量与屏幕上的不一样吗?我花了一些时间来解决它,但是失败了。你有什么想法吗? - Sysphus
当视图包含图像视图时,代码错误:软件渲染不支持硬件位图。 - AAV
@Fahad-Android 这段代码没有改变任何视图背景,所以可能是你代码的另一个部分出现了异常。 - Gil SH

62

对我最有用的投票解决方案不适用于我,因为我的视图是ViewGroup(已从LayoutInflater填充)。 我需要调用view.measure来强制计算视图大小,以便使用view.getMeasuredWidth(Height)获取正确的视图大小。

public static Bitmap getBitmapFromView(View view) {
    view.measure(MeasureSpec.UNSPECIFIED, 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;
}

终于!这里有真正的答案。 - Amila Abeygunasekara
这对我有效。但是字体大小与屏幕不匹配。有人能告诉我为什么吗? - Pranjal Choladhara

31

8

这是一个受到Google Android Maps Utils Icon Generator启发而编写的Kotlin扩展。

fun View.convertToBitmap(): Bitmap {
val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
measure(measureSpec, measureSpec)
layout(0, 0, measuredWidth, measuredHeight)
val r = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888)
r.eraseColor(Color.TRANSPARENT)
val canvas = Canvas(r)
draw(canvas)
return r }

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.getMeasuredHeight(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.translate((-tv.getScrollX()), (-tv.getScrollY()));
    tv.draw(c);
    return b;
}

没有xml:

  private Bitmap createBitmapFromView() {
    TextView tv = new TextView(this);
    tv.setText("Hello Android !!");
    tv.setTextColor(Color.WHITE);
    tv.setBackgroundColor(Color.GRAY);
    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.getMeasuredHeight(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    c.translate((-tv.getScrollX()), (-tv.getScrollY()));
    tv.draw(c);
    return b;
}

太棒了,谢谢!我在类似的解决方案上花了几个小时,但都没有成功。你能告诉我们更多关于这段代码吗?为什么需要使用makeMeasureSpec?为什么需要对画布进行平移操作? - Caio Mar
这里有一些关于View.MeasureSpec的文档,供感兴趣的人参考:https://developer.android.com/reference/android/view/View.MeasureSpec - Caio Mar

3

所有在画布上使用绘图的答案都无法与GLSurfaceView一起使用。

要将GLSurfaceView的内容捕获到位图中,您应该考虑使用gl.glReadPixelsRenderer :: onDrawFrame()中实现自定义方法。

此处已发布解决方案片段here


1

只需使用以下代码即可实现:
这将把任何视图(FrameLayout/LinearLayout/RelativeLayout等)转换为位图。

private Bitmap getBitmapFromView(View view) {
        view.setDrawingCacheEnabled(true);
        return view.getDrawingCache();
}

已被弃用 :( - undefined

0

自API级别24开始,有更好的方法使用PixelCopy。使用示例:

/**
 * use [PixelCopy] to take a snap shoot of the given view
 */
fun copyViewPixelsToBitmap(window: Window?, view: View): Bitmap {
    val snap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)

    val listener = PixelCopy.OnPixelCopyFinishedListener {
        if (it != PixelCopy.SUCCESS) {
            Log.d("copyViewPixelsToBitmap failed with error: $it")
        }
    }
    val xy = IntArray(2)
    view.getLocationInWindow(xy)

    val rect = Rect(xy[0], xy[1], xy[0] + view.width, xy[1] + view.height)
    window?.let {
        PixelCopy.request(it, rect, snap, listener,
            Handler(Looper.getMainLooper()))
    }
    return snap
}

0

要获取与屏幕上显示完全相同的位图,您可以在视图显示后使用Runnable:



void viewToBitmap(View view) {
  view.post(new Runnable() {
      @Override
      public void run() {
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        
        // Do stuff
      }
  });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接