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

บันทึกเสมอว่าแคชการวาดเป็นโมฆะและตั้งค่าบิตแมปเป็น null?

ฉันต้องวาดมุมมองก่อนที่จะตั้งค่าแคชหรือไม่?

ขอบคุณ!


1
stackoverflow.com/questions/9791714/…หลีกเลี่ยงการgetDrawingCache()ใช้View#drawเพื่อCanvasเข้าใกล้
Yuraj

คำตอบ:


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 ลองส่งขนาดจริงไปวัดแทน UNSPECIFIED เช่น MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
ยังคงคืนค่า null แม้จะมี MeasureSpec.EXACTLY

ในมุมมองที่ใหญ่พอสิ่งนี้ไม่ได้ผลสำหรับฉัน (อาจเป็นเพราะฉันมีโทรศัพท์ที่มีทรัพยากรหน่วยความจำ จำกัด มาก) คำตอบด้านล่างโดย cV2 ใช้งานได้ดีสำหรับฉัน
Simon Forsberg

@nininho จะดึงจาก imageview โดยไม่ต้องใช้ getdrawingchache () ได้อย่างไร?
Gorgeous_DroidVirus

มันทำงานได้ดี แต่มันมีผลใน UI โปรดช่วยแก้ปัญหานี้
วิเวกราวี

59

ถ้า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
สิ่งที่ดี. อันนี้ใช้ได้ผลสำหรับฉันในขณะที่คนอื่นไม่ทำ มีเหตุผลอะไรที่จะใช้ค่าจากgetLayoutParamsแทน v.getWidth () และ v.getHeight ()?
Simon Forsberg

ขอโทษโดยส่วนตัวไม่สามารถช่วยคุณในคำถามของคุณ: '(-> ดีที่มันได้ผล :)
cV2

@ cV2 ฉันมีรูปวาดบนรูปภาพ แต่ฉันต้องการ getdrawingcache ในการรัน surfaceview .. แล้วฉันจะทำอะไรต่อ
Gorgeous_DroidVirus

4
ฉันได้รับความกว้างและความสูงของข้อยกเว้นต้อง> 0 .............................. โมฆะส่วนตัว takeScreenShot () {สำหรับ (int ฉัน = 1; ฉัน <4; ฉัน ++) {// startDialog (); View view = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (view);}}
akash yadav

2
ฉันคิดว่า "ความกว้างและความสูงของข้อยกเว้นต้องเป็น> 0" เกิดขึ้นเมื่อคุณImageViewยังไม่ได้รับภาพดังนั้นจึงดูเหมือนว่าจะเป็น 0 สิ่งนี้จะเล่นแตกต่างกันไปสำหรับรหัสของคนอื่น แต่โปรดตรวจสอบให้แน่ใจว่าคุณโทรหาloadBitmapFromView()หลังจากนั้น ของคุณImageViewมีรูปภาพ
Azurespot

6

เหตุผลพื้นฐานที่เราได้รับค่าว่างคือมุมมองไม่ได้ถูกหรี่ ความพยายามทั้งหมดโดยใช้ view.getWidth (), view.getLayoutParams (). width ฯลฯ รวมถึง view.getDrawingCache () และ view.buildDrawingCache () จะไร้ประโยชน์ ดังนั้นก่อนอื่นคุณต้องกำหนดขนาดให้กับมุมมองเช่น:

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

(คุณได้ตั้งค่า 'ความกว้าง' และ 'ความสูง' แล้วตามที่คุณต้องการหรือได้รับด้วย WindowManager เป็นต้น)


ดู root = currActivity.getWindow (). getDecorView (). findViewById (android.R.id.content); root.setDrawingCacheEnabled (จริง); root.layout (0, 0, 480, 854); mBitmap = root.getDrawingCache ();
Narender Gusain

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

หากมุมมองที่คุณต้องการจับแสดงจริง ๆ บนหน้าจอ แต่กลับเป็นโมฆะ นั่นหมายความว่าคุณสามารถดูได้ก่อนที่ Window manager จะสร้างขึ้น เค้าโครงบางอย่างมีความซับซ้อนมาก ถ้าเลย์เอาต์มีเลย์เอาต์แบบซ้อน layout_weight..etc จะทำให้รีเลย์เอ้าท์หลายครั้งได้ขนาดที่แน่นอน ทางออกที่ดีที่สุดคือรอจนกว่าตัวจัดการหน้าต่างจะทำงานเสร็จแล้วจึงรับสกรีนช็อต ลองใส่ getDrawingCache () ในตัวจัดการ


1

คำตอบของ @ cV2 และ @ nininho ใช้ได้ผลกับฉัน

อีกสาเหตุหนึ่งที่ฉันพบวิธีที่ยากคือมุมมองที่ฉันมีกำลังสร้างมุมมองที่มีความกว้างและความสูงเป็น 0 ( เช่นจินตนาการว่ามี TextView ที่มีข้อความสตริงของสตริงว่างเปล่า ) ในกรณีนี้ getDrawingCache จะคืนค่า null ดังนั้นอย่าลืมตรวจสอบให้ดี หวังว่าจะช่วยให้บางคนออกไปที่นั่น


1

ข้อผิดพลาดที่อาจจะ bacause ของคุณดูใหญ่เกินไปที่จะพอดีกับการวาดภาพแคช

ฉันได้รับคำอธิบายปัญหา "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();
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.