Android View.getDrawingCache null döndürüyor, yalnızca null


97

Biri bana nedenini açıklamaya çalışır mı

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

HER ZAMAN çizim önbelleğinin boş olduğunu günlüğe kaydeder ve bitmap'i boş olarak ayarlar.

Önbellek ayarlanmadan önce görünümü gerçekten çizmem gerekiyor mu?

Teşekkürler!


1
stackoverflow.com/questions/9791714/... önlemek kullanarak getDrawingCache()kullanım View#drawiçin Canvasbir yaklaşım
Yuraj

Yanıtlar:


240

Ben de bu sorunu yaşıyordum ve şu cevabı buldum:

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 ölçümü içerik boyutuna bağlıdır, bu nedenle web sayfası henüz yüklenmemişse, 0 ölçüsü alırsınız. Ölçmek için MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY) gibi UNSPECIFIED yerine ölçmek için geçmeyi deneyin;
Marcio Covre

3
Yine de MeasureSpec.EXACTLY ile bile null döndürür.

Yeterince büyük bir görüşe göre, bu benim için işe yaramadı. (Muhtemelen hafıza kaynakları çok sınırlı olan bir telefonum olduğu için). Aşağıdaki cV2 cevabı benim için iyi çalıştı.
Simon Forsberg

@nininho getdrawingchache () yöntemini kullanmadan imageview'den nasıl çizim yapılabilir?
Gorgeous_DroidVirus

İyi çalışıyor. Ancak kullanıcı arayüzünde etkiler. Lütfen bu sorunu çözmeye yardımcı olun.
Vivek Ravi

59

eğer getDrawingCacheher zaman returning nulladamlar: Bu kullanın:

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

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


1
İyi bir. Bu benim için çalıştı, diğerleri işe yaramadı. Değerleri getLayoutParamsv.getWidth () ve v.getHeight () yerine kullanmak için herhangi bir neden var mı ?
Simon Forsberg

üzgünüm, şahsen, sorunuzla ilgili size yardımcı olamam: '(-> işe yaraması güzel :)
cV2

@ cV2 Resimlerle ilgili çizimi aldım, ancak yüzey görünümünü çalıştırırken getdrawingcache almam gerekiyor .. o zaman ne yapabilirim?
Gorgeous_DroidVirus

4
İstisna genişliği ve yüksekliği> 0 .............................. özel void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Görünüm görünümü = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (görünüm);}}
akash yadav

2
"İstisna genişliği ve yüksekliği, ImageViewhenüz bir resim almadığınızda > 0 olmalıdır" diye düşünüyorum , bu nedenle 0 gibi görünüyor. Bu, farklı kişilerin kodları için farklı bir şekilde oynayacaktır, ancak aramanızın loadBitmapFromView()kesinlikle sonra olduğundan emin olun. senin ImageViewbir resim içeriyor.
Azurespot

6

Birinin boş almasının temel nedeni, görüşün boyutlandırılmamış olmasıdır. Bu durumda, view.getDrawingCache () ve view.buildDrawingCache () dahil, view.getWidth (), view.getLayoutParams (). Width vb. Kullanılarak yapılan tüm girişimler işe yaramaz. Bu nedenle, önce görünüme boyutları ayarlamanız gerekir, örneğin:

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

('Genişliği' ve 'yüksekliği' istediğiniz gibi ayarladınız veya WindowManager, vb. İle edindiniz.)


Görünüm root = currActivity.getWindow (). GetDecorView (). FindViewById (android.R.id.content); root.setDrawingCacheEnabled (true); root.layout (0, 0, 480, 854); mBitmap = root.getDrawingCache ();
Narender Gusain

4

Onun yerine bunu kullanıyorum.

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

3

En iyi 4me çalışın

    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

Yakalamak istediğiniz görünüm ekranda gerçekten gösteriliyorsa, ancak boş dönüyor. Bu, görünümü Pencere yöneticisi oluşturmadan önce yakaladığınız anlamına gelir. Bazı düzenler çok karmaşıktır. Düzen, iç içe yerleştirilmiş düzenler, layout_weight..etc içeriyorsa, birkaç kez geçişin tam boyuta ulaşmasına neden olur. En iyi çözüm, pencere yöneticisinin işi bitirmesini ve ardından ekran görüntüsünü almasını beklemektir. İşleyiciye getDrawingCache () koymayı deneyin.


1

@ cV2 ve @ nininho'nun cevapları benim için çalışıyor.

Zor yoldan bulmamın diğer nedenlerinden biri, sahip olduğum görünümün genişliği ve yüksekliği 0 olan bir görünüm oluşturmasıydı ( yani, boş bir dizenin dize metnine sahip bir TextView olduğunu hayal edin ). Bu durumda getDrawingCache null döndürecektir, bu yüzden bunu kontrol ettiğinizden emin olun. Umarım bu bazı insanlara yardımcı olur.


1

Hata, Görünümünüzün çizim önbelleğine sığmayacak kadar büyük olmasından kaynaklanıyor olabilir .

"View.getDrawingCache null döndürüyor" sorunumun açıklamasını günlüklerimden aldım:

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

Android dokümanları ayrıca şunu da söylüyor : Android cihazların tek bir uygulamada kullanılabilen 16MB kadar az belleği olabilir. Bu yüzden büyük bitmap yükleyemezsiniz.


1

Görüntüye göre dinamik olarak n adet görüntü oluşturmaya çalışıyorum.

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

Bu kodun birine yardımcı olacağını düşünüyorum ..


-1

Bu, bitmap almanın basit ve etkili yolu

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();
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.