Android View.getDrawingCache restituisce null, solo null


97

Qualcuno potrebbe provare a spiegarmi il motivo

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

SEMPRE registra che la cache di disegno è nulla e imposta la bitmap su zero?

Devo effettivamente disegnare la vista prima che la cache sia impostata?

Grazie!


1
stackoverflow.com/questions/9791714/… evita di usare l' getDrawingCache()uso View#drawper Canvasavvicinarti
Yuraj

Risposte:


240

Avevo anche questo problema e ho trovato questa risposta:

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
La misura di WebView dipende dalla dimensione del contenuto, quindi se la pagina web non è ancora caricata otterrai una misura di 0. Prova a passare la dimensione reale da misurare invece di non specificata come MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
Restituisce ancora null anche con MeasureSpec.EXACTLY.

Su una vista abbastanza grande, questo non ha funzionato per me. (Forse perché ho un telefono con risorse di memoria molto limitate). La risposta di seguito da cV2 ha funzionato bene per me.
Simon Forsberg

@nininho come ottenere drawable da imageview senza utilizzare il metodo getdrawingchache ()?
Gorgeous_DroidVirus

Funziona bene. Ma influisce sull'interfaccia utente. Aiutaci a risolvere questo problema.
Vivek Ravi

58

se getDrawingCacheè sempre returning nullragazzi: usa questo:

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

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


1
Bene. Questo ha funzionato per me mentre gli altri no. C'è qualche motivo per utilizzare i valori da getLayoutParamsinvece di v.getWidth () e v.getHeight ()?
Simon Forsberg

mi dispiace, personalmente, non posso aiutarti con la tua domanda: '(-> bello che abbia funzionato :)
cV2

@ cV2 ho il disegno sulle immagini, ma ho bisogno di ottenere il getdrawingcache durante l'esecuzione di surfaceview .. quindi cosa posso fare dopo?
Gorgeous_DroidVirus

4
ottengo che la larghezza e l'altezza dell'eccezione siano> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Visualizza vista = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (view);}}
akash yadav

2
Penso che `la larghezza e l'altezza dell'eccezione debbano essere> 0` si verifica quando non hai ImageViewancora ricevuto un'immagine, quindi sembra essere 0. Questo giocherebbe in modo diverso per il codice di persone diverse, ma assicurati che la tua chiamata a loadBitmapFromView()sia sicuramente dopo il tuo ImageViewcontiene un'immagine.
Azurespot

6

Il motivo principale per cui si ottengono valori nulli è che la vista non viene dimenticata. Tutti i tentativi quindi, utilizzando view.getWidth (), view.getLayoutParams (). Width, ecc., Inclusi view.getDrawingCache () e view.buildDrawingCache (), sono inutili. Quindi, devi prima impostare le dimensioni della vista, ad esempio:

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

(Hai già impostato 'larghezza' e 'altezza' come preferisci o le hai ottenute con WindowManager, ecc.)


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

4

Lo sto usando invece.

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

3

Lavora meglio 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

Se la vista che vuoi catturare viene davvero mostrata sullo schermo, ma restituisce null. Ciò significa che si cattura la vista prima che Window manager la generi. Alcuni layout sono molto complicati. Se layout include layout annidati, layout_weight..etc, fa sì che più volte il relayout abbia la dimensione esatta. La soluzione migliore è attendere che il gestore delle finestre finisca il lavoro e quindi ottenere la schermata. Prova a mettere getDrawingCache () nel gestore.


1

Le risposte di @ cV2 e @ nininho funzionano entrambe per me.

Uno degli altri motivi per cui ho scoperto nel modo più duro è stato che la vista che avevo stava generando una vista con larghezza e altezza 0 ( cioè immagina di avere una TextView con una stringa di testo di una stringa vuota ). In questo caso, getDrawingCache restituirà null, quindi assicurati di controllarlo. Spero che questo aiuti alcune persone là fuori.


1

L'errore potrebbe essere dovuto al fatto che il tuo file vista è troppo grande per adattarsi alla cache di disegno .

Ho ottenuto la spiegazione del mio problema "View.getDrawingCache restituisce null" dai miei log:

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

La documentazione di Android dice anche : i dispositivi Android possono avere solo 16 MB di memoria disponibile per una singola applicazione. Questo è il motivo per cui non puoi caricare bitmap di grandi dimensioni.


1

Sto cercando di creare dinamicamente il numero n di immagini in base alla visualizzazione.

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

Penso che questo codice aiuterà qualcuno ..


-1

Questo è il modo semplice ed efficiente per ottenere 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();
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.