Android View.getDrawingCache trả về null, chỉ null


97

Có ai vui lòng giải thích cho tôi tại sao không

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!!!
}

LUÔN LUÔN ghi lại rằng bộ nhớ cache của bản vẽ là null và đặt bitmap thành null?

Tôi có phải thực sự vẽ chế độ xem trước khi bộ đệm được đặt không?

Cảm ơn!


1
stackoverflow.com/questions/9791714/... tránh sử dụng getDrawingCache()sử dụng View#drawđể Canvastiếp cận
Yuraj

Câu trả lời:


240

Tôi cũng gặp vấn đề này và tìm thấy câu trả lời sau:

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
Việc đo lường WebView phụ thuộc vào kích thước nội dung, vì vậy nếu trang web chưa được tải, bạn sẽ nhận được số đo là 0. Hãy thử chuyển kích thước thực để đo lường thay vì UNSPECIFIED như MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
Vẫn trả về null ngay cả với MeasureSpec.EXACTLY.

Trên một góc nhìn đủ lớn, điều này không hiệu quả với tôi. (Có thể vì tôi có một chiếc điện thoại có tài nguyên bộ nhớ rất hạn chế). Câu trả lời dưới đây của cV2 phù hợp với tôi.
Simon Forsberg

@nininho làm cách nào để có thể drawable từ imageview mà không sử dụng phương thức getdrawingchache ()?
Gorgeous_DroidVirus

Nó hoạt động tốt. Nhưng nó ảnh hưởng đến giao diện người dùng. Xin vui lòng giúp đỡ để giải quyết vấn đề này.
Vivek Ravi

58

nếu getDrawingCacheluôn luôn là returning nullguys: sử dụng cái này:

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;
}

Tham khảo: https://stackoverflow.com/a/6272951/371749


1
Tốt. Cái này làm việc cho tôi trong khi những cái khác thì không. Có lý do gì để sử dụng các giá trị từ getLayoutParamsthay vì v.getWidth () và v.getHeight () không?
Simon Forsberg

xin lỗi, cá nhân, không thể giúp bạn với câu hỏi của bạn: '(-> tốt đẹp mà nó làm việc :)
CV2

@ cV2 tôi có bản vẽ trên hình ảnh, nhưng tôi cần lấy getdrawingcache khi chạy surfaceview .. sau đó tôi có thể làm gì tiếp theo?
Gorgeous_DroidVirus

4
tôi nhận được ngoại lệ chiều rộng và chiều cao phải> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); View view = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (view);}}
akash yadav

2
Tôi nghĩ rằng `` chiều rộng và chiều cao ngoại lệ phải> 0` xảy ra khi bạn ImageViewchưa nhận được hình ảnh, vì vậy nó có vẻ là 0. Điều này sẽ diễn ra khác nhau đối với mã của những người khác nhau, nhưng hãy đảm bảo cuộc gọi của bạn loadBitmapFromView()chắc chắn là sau của bạn ImageViewcó chứa một hình ảnh.
Azurespot

6

Lý do cơ bản khiến người ta nhận được nulls là chế độ xem không được phân bổ. Sau đó, tất cả các nỗ lực sử dụng view.getWidth (), view.getLayoutParams (). Width, v.v., bao gồm view.getDrawingCache () và view.buildDrawingCache (), đều vô ích. Vì vậy, trước tiên bạn cần đặt kích thước cho chế độ xem, ví dụ:

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

(Bạn đã đặt 'chiều rộng' và 'chiều cao' theo ý muốn hoặc lấy chúng bằng WindowManager, v.v.)


Xem root = currActivity.getWindow (). GetDecorView (). FindViewById (android.R.id.content); root.setDrawingCacheEnabled (true); root.layout (0, 0, 480, 854); mBitmap = root.getDrawingCache ();
Narender Gusain

4

Tôi đang sử dụng cái này để thay thế.

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

3

Làm việc tốt nhất 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

Nếu chế độ xem bạn muốn bắt thực sự hiển thị trên màn hình, nhưng nó trả về giá trị rỗng. Điều đó có nghĩa là bạn bắt được chế độ xem trước khi trình quản lý Window tạo nó. Một số bố cục rất phức tạp. Nếu bố cục bao gồm các bố cục lồng nhau, layout_weight..vv, nó gây ra nhiều lần chuyển tiếp để có được kích thước chính xác. Giải pháp tốt nhất là đợi cho đến khi trình quản lý cửa sổ hoàn thành công việc và sau đó nhận ảnh chụp màn hình. Cố gắng đặt getDrawingCache () trong trình xử lý.


1

Câu trả lời của @ cV2 và @ nininho đều phù hợp với tôi.

Một trong những lý do khác khiến tôi phát hiện ra một cách khó khăn là chế độ xem mà tôi đã tạo ra một chế độ xem có chiều rộng và chiều cao bằng 0 ( tức là hãy tưởng tượng có một TextView với văn bản chuỗi của một chuỗi rỗng ). Trong trường hợp này, getDrawingCache sẽ trả về null, vì vậy hãy đảm bảo kiểm tra điều đó. Hy vọng rằng sẽ giúp một số người ngoài đó.


1

Lỗi có thể là do Chế độ xem của bạn quá lớn để vừa với bộ đệm bản vẽ .

Tôi đã nhận được lời giải thích về sự cố "View.getDrawingCache trả về null" từ nhật ký của mình:

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

Tài liệu Android cũng cho biết : Các thiết bị Android chỉ có thể có ít nhất 16MB bộ nhớ cho một ứng dụng. Đó là lý do tại sao bạn không thể tải bitmap lớn.


1

Tôi đang cố gắng tạo n số hình ảnh động dựa trên chế độ xem.

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();
}

Tôi nghĩ mã này sẽ giúp ai đó ..


-1

Đây là cách đơn giản và hiệu quả để lấy bitmap

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();
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.