Android View.getDrawingCache mengembalikan null, hanya null

97

Adakah yang mau mencoba menjelaskan kepada saya mengapa

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

SELALU mencatat bahwa cache gambar adalah nol, dan menyetel bitmap ke nol?

Apakah saya harus benar-benar menggambar tampilan sebelum cache disetel?

Terima kasih!

Bex
sumber
1
stackoverflow.com/questions/9791714/... menghindari menggunakan getDrawingCache()penggunaan View#drawuntuk Canvaspendekatan
Yuraj

Jawaban:

240

Saya juga mengalami masalah ini dan menemukan jawaban ini:

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
Marcio Covre
sumber
1
Pengukuran WebView bergantung pada ukuran konten, jadi jika halaman web belum dimuat Anda akan mendapatkan ukuran 0. Coba teruskan ukuran sebenarnya ke pengukuran alih-alih UNSPECIFIED seperti MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre
3
Masih mengembalikan nol bahkan dengan MeasureSpec.EXACTLY.
Pada tampilan yang cukup besar, ini tidak berhasil untuk saya. (Mungkin karena saya memiliki ponsel dengan sumber daya memori yang sangat terbatas). Jawaban di bawah oleh cV2 bekerja dengan baik untuk saya.
Simon Forsberg
@nininho bagaimana cara mendapatkan drawable dari imageview tanpa menggunakan metode getdrawingchache ()?
Gorgeous_DroidVirus
Ini bekerja dengan baik. Tapi itu berpengaruh di UI. Tolong bantu untuk memecahkan masalah ini.
Vivek Ravi
58

jika getDrawingCacheselalu returning nullguys: gunakan ini:

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

Referensi: https://stackoverflow.com/a/6272951/371749

cV2
sumber
1
Bagus. Yang ini berhasil untuk saya sementara yang lain tidak. Apakah ada alasan untuk menggunakan nilai dari getLayoutParamsalih-alih v.getWidth () dan v.getHeight ()?
Simon Forsberg
maaf, secara pribadi, tidak dapat membantu Anda dengan pertanyaan Anda: '(-> bagus itu berhasil :)
cV2
@ cV2 saya mendapat gambar pada gambar, tetapi saya perlu mendapatkan getdrawingcache saat menjalankan surfaceview .. lalu apa yang dapat saya lakukan selanjutnya?
Gorgeous_DroidVirus
4
saya mendapatkan pengecualian lebar dan tinggi harus> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Tampilan tampilan = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (view);}}
akash yadav
2
Saya pikir `pengecualian lebar dan tinggi harus> 0` muncul ketika Anda ImageViewbelum menerima gambar, jadi tampaknya 0. Ini akan bermain berbeda untuk kode orang yang berbeda, tapi pastikan panggilan Anda ke loadBitmapFromView()pasti setelah Anda ImageViewberisi gambar.
Azurespot
6

Alasan dasar seseorang mendapatkan null adalah karena view tidak berdimensi. Semua upaya kemudian, menggunakan view.getWidth (), view.getLayoutParams (). Width, dll., Termasuk view.getDrawingCache () dan view.buildDrawingCache (), tidak berguna. Jadi, Anda harus terlebih dahulu menyetel dimensi ke tampilan, misalnya:

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

(Anda telah mengatur 'width' dan 'height' sesuka Anda atau mendapatkannya dengan WindowManager, dll.)

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

Saya menggunakan ini sebagai gantinya.

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

Kerja terbaik 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);
Alexey Kurilov
sumber
2

Jika tampilan yang Anda inginkan menangkap benar-benar muncul di layar, tetapi mengembalikan null. Itu berarti Anda menangkap tampilan sebelum pengelola Jendela membuatnya. Beberapa tata letak sangat rumit. Jika layout menyertakan layout bersarang, layout_weight..etc, ini menyebabkan beberapa kali relai mendapatkan ukuran yang tepat. Solusi terbaik adalah menunggu sampai window manager menyelesaikan pekerjaan dan kemudian mendapatkan screen shot. Coba letakkan getDrawingCache () di handler.

Kislingk
sumber
1

Jawaban @ cV2 dan @ nininho bekerja untuk saya.

Salah satu alasan lain yang saya temukan dengan susah payah adalah bahwa tampilan yang saya miliki menghasilkan tampilan yang memiliki lebar dan tinggi 0 ( yaitu bayangkan memiliki TextView dengan teks string dari string kosong ). Dalam kasus ini, getDrawingCache akan mengembalikan null, jadi pastikan untuk memeriksanya. Harapan yang membantu beberapa orang di luar sana.

Bundeeteddee
sumber
1

Kesalahannya mungkin karena View Anda terlalu besar untuk dimasukkan ke dalam cache gambar .

Saya mendapat penjelasan tentang masalah "View.getDrawingCache mengembalikan null" dari log saya:

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

Dokumen Android juga mengatakan : Perangkat Android hanya dapat memiliki memori 16MB yang tersedia untuk satu aplikasi. Itulah mengapa Anda tidak dapat memuat bitmap besar.

Yuliia Ashomok
sumber
1

Saya mencoba membuat jumlah n gambar secara dinamis berdasarkan tampilan.

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

Saya pikir kode ini akan membantu seseorang ..

Harish
sumber
-1

Ini cara sederhana dan efisien untuk mendapatkan 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();
    }
Nilesh B
sumber