Android View.getDrawingCache返回null,仅返回null


97

任何人都可以尝试向我解释为什么

public void addView(View child) {
  child.setDrawingCacheEnabled(true);
  child.setWillNotCacheDrawing(false);
  child.setWillNotDraw(false);
  child.buildDrawingCache();
  if(child.getDrawingCache() == null) { //TODO Make this work!
    Log.w("View", "View child's drawing cache is null");
  }
  setImageBitmap(child.getDrawingCache()); //TODO MAKE THIS WORK!!!
}

始终记录图形缓存为空,并将位图设置为空吗?

在设置缓存之前,我是否必须实际绘制视图?

谢谢!


1
stackoverflow.com/questions/9791714/...忌用getDrawingCache()使用View#drawCanvas的方法
Yuraj

Answers:


240

我也有这个问题,找到了这个答案:

v.setDrawingCacheEnabled(true);

// this is the important code :)  
// Without it the view will have a dimension of 0,0 and the bitmap will be null          
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

1
WebView的度量取决于内容的大小,因此,如果尚未加载网页,您将获得0的度量。尝试将实际尺寸传递给度量,而不是像MeasureSpec.makeMeasureSpec(800,MeasureSpec.EXACTLY)这样的未传递度量;
Marcio Covre 2012年

3
即使使用MeasureSpec.EXACTLY仍然返回null。

从足够大的角度来看,这对我不起作用。(可能是因为我的手机内存资源非常有限)。以下cV2的答案对我来说效果很好。
西蒙·福斯伯格

@nininho如何在不使用getdrawingchache()方法的情况下从imageview获取可绘制图像?
Gorgeous_DroidVirus 2014年

效果很好。但这会影响UI。请帮助解决此问题。
Vivek Ravi 2014年

58

如果getDrawingCache始终是returning null伙计:请使用以下命令:

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(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
     v.draw(c);
     return b;
}

参考:https : //stackoverflow.com/a/6272951/371749


1
好一个 这个为我工作,而其他人则没有。是否有任何理由使用from中的值getLayoutParams代替v.getWidth()和v.getHeight()?
西蒙·佛斯伯格

抱歉,就您个人而言,不能为您提供帮助:'(--效果很好:)
cV2

@ cV2我在图像上绘图,但是我需要在运行surfaceview时获取getdrawingcache。.那么我下一步该怎么办?
Gorgeous_DroidVirus 2014年

4
我收到异常宽度和高度必须> 0 ...................... private void takeScreenShot(){for(int i = 1; i <4; i ++){// startDialog(); 视图视图= ScreenShotActivity.this.findViewById(R.id.relativelayout); 位图位图= loadBitmapFromView(view);}}
akash yadav 2014年

2
我认为`异常宽度和高度必须大于0'是在您ImageView尚未收到图像时发生的,因此它看起来是0。这对于不同的人的代码来说会有所不同,但是请确保loadBitmapFromView()在您ImageView包含一张图片。
Azurespot 2015年

6

一个为空的基本原因是没有提及该视图。然后,使用view.getWidth(),view.getLayoutParams()。width等的所有尝试(包括view.getDrawingCache()和view.buildDrawingCache())都是没有用的。因此,您首先需要为视图设置尺寸,例如:

view.layout(0, 0, width, height);

(您已经根据需要设置了'width'和'height'或通过WindowManager等获得了它们。)


查看根= currActivity.getWindow()。getDecorView()。findViewById(android.R.id.content); root.setDrawingCacheEnabled(true); root.layout(0,0,480,854); mBitmap = root.getDrawingCache();
Narender Gusain'Mar

4

我用这个代替。

myView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Bitmap bitmap = Bitmap.createBitmap(myView.getDrawingCache());
        }
    });

3

最好的4me

    Bitmap bitmap = Bitmap.createBitmap( screen.getMeasuredWidth(), screen.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    screen.layout(0, 0, screen.getMeasuredWidth(), screen.getMeasuredHeight());
    screen.draw(canvas);

2

如果要捕获的视图确实显示在屏幕上,但返回null。这意味着您需要在窗口管理器生成视图之前捕获视图。一些布局非常复杂。如果layout包含嵌套的layouts,layout_weight..etc等,它将导致数次重排以准确获得尺寸。最好的解决方案是等到窗口管理器完成工作然后再截屏。尝试将getDrawingCache()放入处理程序中。


1

@ cV2和@nininho的答案都对我有用。

我发现困难的方法的另一个原因之一是,我所生成的视图正在生成一个宽度和高度为0的视图(即,假设有一个TextView的字符串文本为空字符串)。在这种情况下,getDrawingCache将返回null,因此请务必进行检查。希望可以帮助一些人。


1

该错误可能是由于您的View太大而无法容纳到图形缓存中

我从日志中得到了“ View.getDrawingCache返回null”问题的解释:

W/View: View too large to fit into drawing cache, needs 19324704 bytes, only 16384000 available

Android文档还说单个应用程序可以为Android设备提供最少16MB的内存。这就是为什么您不能加载大位图的原因。


1

我试图基于视图动态创建n个图像。

LayoutInflater infalter=(LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View addview=infalter.inflate(R.layout.barcode_image_list_row_item, null);
final ImageView imv=(ImageView) addview.findViewById(R.id.imageView1);
final TextView tv=(TextView) addview.findViewById(R.id.textView1);

try {         
    final Bitmap bitmap = encodeAsBitmap(""+value, BarcodeFormat.CODE_128, 600, 300);

    if (bitmap != null) {
        // TODO Auto-generated method stub
        imv.setImageBitmap(bitmap);
        tv.setText(value);

        addview.setDrawingCacheEnabled(true);

        // this is the important code :)  
        // Without it the view will have a dimension of 0,0 and the bitmap will be null          
        addview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        addview.layout(0, 0, addview.getMeasuredWidth(), addview.getMeasuredHeight()); 

        addview.buildDrawingCache(true);
        Bitmap b = Bitmap.createBitmap(addview.getDrawingCache());
        addview.setDrawingCacheEnabled(false); // clear drawing cache
        // saving the bitmap   
        savebarcode(b,value);
    }
} catch (WriterException e) {
    e.printStackTrace();
}

我认为这段代码将对某人有所帮助。


-1

这是获取位图的简单有效的方法

public void addView(View v) {
        v.setDrawingCacheEnabled(true);
        v.buildDrawingCache();

        Bitmap bitmap = v.getDrawingCache();

        if(bitmap == null) {
            // bitmap is null
            // do whatever you want
        } else {
            setImageBitmap(bitmap);
        }
        v.setDrawingCacheEnabled(false);
        v.destroyDrawingCache();
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.