Android View.getDrawingCache gibt null zurück, nur null

97

Würde jemand bitte versuchen mir zu erklären warum

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

Protokolliert IMMER, dass der Zeichnungscache null ist, und setzt die Bitmap auf null?

Muss ich die Ansicht tatsächlich zeichnen, bevor der Cache festgelegt wird?

Vielen Dank!

Bex
quelle
1
stackoverflow.com/questions/9791714/… vermeiden Sie die getDrawingCache()Verwendung View#drawder CanvasAnnäherung
Yuraj

Antworten:

240

Ich hatte auch dieses Problem und fand diese Antwort:

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
quelle
1
Die WebView-Messung hängt von der Inhaltsgröße ab. Wenn die Webseite noch nicht geladen ist, erhalten Sie ein Maß von 0. Versuchen Sie, die tatsächliche Größe anstelle von UNSPECIFIED wie MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY) zu übergeben.
Marcio Covre
3
Gibt auch mit MeasureSpec.EXACTLY immer noch null zurück.
Aus einer ausreichend großen Sicht hat dies bei mir nicht funktioniert. (Möglicherweise, weil ich ein Telefon mit sehr begrenzten Speicherressourcen habe). Die Antwort von cV2 unten hat für mich gut funktioniert.
Simon Forsberg
@nininho Wie kann man aus der Bildansicht ohne die Methode getdrawingchache () zeichnen?
Gorgeous_DroidVirus
Es funktioniert gut. Aber es wirkt sich auf die Benutzeroberfläche aus. Bitte helfen Sie, dieses Problem zu lösen.
Vivek Ravi
58

Wenn getDrawingCachees immer returning nullJungs gibt: benutze dies:

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

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

cV2
quelle
1
Gut. Dieser arbeitete für mich, während die anderen nicht arbeiteten. Gibt es einen Grund, die Werte von getLayoutParamsanstelle von v.getWidth () und v.getHeight () zu verwenden?
Simon Forsberg
Entschuldigung, ich persönlich kann Ihnen bei Ihrer Frage nicht helfen: '(-> schön, dass es funktioniert hat :)
cV2
@ cV2 Ich habe die Zeichnung auf Bildern, aber ich muss den getdrawingcache auf laufender Oberflächenansicht bekommen .. was kann ich dann als nächstes tun?
Gorgeous_DroidVirus
4
Ich erhalte Ausnahme Breite und Höhe müssen> 0 sein .............................. 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
Ich denke, die "Ausnahmebreite und -höhe muss> 0 sein" tritt auf, wenn Sie ImageViewnoch kein Bild erhalten haben. Es scheint also 0 zu sein. Dies würde für den Code verschiedener Personen unterschiedlich ablaufen , aber stellen Sie sicher, dass Ihr Anruf loadBitmapFromView()definitiv danach erfolgt Ihr ImageViewenthält ein Bild.
Azurespot
6

Der Hauptgrund, warum man Nullen bekommt, ist, dass die Ansicht nicht verkleinert ist. Alle Versuche mit view.getWidth (), view.getLayoutParams (). Width usw., einschließlich view.getDrawingCache () und view.buildDrawingCache (), sind nutzlos. Sie müssen also zuerst die Abmessungen für die Ansicht festlegen, z.

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

(Sie haben bereits 'Breite' und 'Höhe' nach Ihren Wünschen eingestellt oder mit WindowManager usw. erhalten.)

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

Ich benutze dies stattdessen.

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

Arbeite am besten 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
quelle
2

Wenn die Ansicht, die Sie fangen möchten, wirklich auf dem Bildschirm angezeigt wird, aber null zurückgibt. Das heißt, Sie erfassen die Ansicht, bevor der Fenstermanager sie generiert. Einige Layouts sind sehr kompliziert. Wenn das Layout verschachtelte Layouts (layout_weight..etc) enthält, erhält das Relayout mehrmals genau die richtige Größe. Die beste Lösung besteht darin, zu warten, bis der Fenstermanager den Auftrag beendet hat, und dann einen Screenshot zu erhalten. Versuchen Sie, getDrawingCache () in den Handler einzufügen.

Kislingk
quelle
1

Die Antworten von @ cV2 und @ nininho funktionieren beide für mich.

Einer der anderen Gründe, warum ich es auf die harte Tour herausgefunden habe, war, dass die Ansicht, die ich hatte, eine Ansicht mit einer Breite und Höhe von 0 erzeugte ( dh stellen Sie sich eine Textansicht mit einem Zeichenfolgentext einer leeren Zeichenfolge vor ). In diesem Fall gibt getDrawingCache null zurück. Überprüfen Sie dies daher unbedingt. Hoffe das hilft einigen Leuten da draußen.

Bundeeteddee
quelle
1

Der Fehler kann darin liegen, dass Ihre Ansicht zu groß ist, um in den Zeichnungscache zu passen .

Ich habe die Erklärung meines Problems "View.getDrawingCache gibt null zurück" aus meinen Protokollen erhalten:

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

In den Android-Dokumenten heißt es außerdem : Auf Android-Geräten können nur 16 MB Speicher für eine einzelne Anwendung verfügbar sein. Deshalb können Sie keine große Bitmap laden.

Yuliia Ashomok
quelle
1

Ich versuche, die n Anzahl der Bilder dynamisch basierend auf der Ansicht zu erstellen.

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

Ich denke, dieser Code wird jemandem helfen ..

Harish
quelle
-1

Dies ist der einfache und effiziente Weg, um eine Bitmap zu erhalten

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.
quelle