Android View.getDrawingCache renvoie null, uniquement null

97

Quelqu'un pourrait-il essayer de m'expliquer pourquoi

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

Consigne TOUJOURS que le cache de dessin est nul et définit le bitmap sur null?

Dois-je réellement dessiner la vue avant de définir le cache?

Merci!

Bex
la source
1
stackoverflow.com/questions/9791714/… éviter d'utiliser l' getDrawingCache()utilisation View#drawpour Canvasapprocher
Yuraj

Réponses:

240

J'avais ce problème aussi et j'ai trouvé cette réponse:

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
la source
1
La mesure WebView dépend de la taille du contenu, donc si la page Web n'est pas encore chargée, vous obtiendrez une mesure de 0. Essayez de passer la taille réelle à mesurer au lieu de UNSPECIFIED comme MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre
3
Renvoie toujours null même avec MeasureSpec.EXACTLY.
Sur une vue assez large, cela n'a pas fonctionné pour moi. (Peut-être parce que j'ai un téléphone avec des ressources mémoire très limitées). La réponse ci-dessous par cV2 a bien fonctionné pour moi.
Simon Forsberg
@nininho comment obtenir un dessin à partir d'imageview sans utiliser la méthode getdrawingchache ()?
Gorgeous_DroidVirus
Ça marche bien. Mais cela affecte l'interface utilisateur. Veuillez aider à résoudre ce problème.
Vivek Ravi
58

si getDrawingCachec'est toujours les returning nullgars: utilisez ceci:

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

Référence: https://stackoverflow.com/a/6272951/371749

cV2
la source
1
Bon. Celui-ci a fonctionné pour moi tandis que les autres n'ont pas fonctionné. Y a-t-il une raison d'utiliser les valeurs de getLayoutParamsau lieu de v.getWidth () et v.getHeight ()?
Simon Forsberg
désolé, personnellement, je ne peux pas vous aider avec votre question: '(-> bien que cela ait fonctionné :)
cV2
@ cV2 J'ai le dessin sur les images, mais j'ai besoin d'obtenir le getdrawingcache sur la vue de surface en cours d'exécution .. que puis-je faire ensuite?
Gorgeous_DroidVirus
4
j'obtiens une largeur et une hauteur d'exception doivent être> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Vue vue = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (vue);}}
akash yadav
2
Je pense que «la largeur et la hauteur de l'exception doivent être> 0» survient lorsque vous n'avez ImageViewpas encore reçu d'image, il semble donc être 0. Cela se jouerait différemment pour le code de différentes personnes, mais assurez-vous que votre appel loadBitmapFromView()est définitivement après votre ImageViewcontient une image.
Azurespot
6

La raison fondamentale pour laquelle on obtient des valeurs nulles est que la vue n'est pas dimensionnée. Toutes les tentatives alors, en utilisant view.getWidth (), view.getLayoutParams (). Width, etc., y compris view.getDrawingCache () et view.buildDrawingCache (), sont inutiles. Donc, vous devez d'abord définir les dimensions de la vue, par exemple:

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

(Vous avez déjà défini 'width' et 'height' comme vous le souhaitez ou les avez obtenus avec WindowManager, etc.)

Apostolos
la source
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

J'utilise ça à la place.

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

Travaille mieux 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
la source
2

Si la vue que vous voulez capturer s'affiche vraiment à l'écran, mais qu'elle renvoie null. Cela signifie que vous capturez la vue avant que le gestionnaire de fenêtres ne la génère. Certaines mises en page sont très compliquées. Si la mise en page comprend des mises en page imbriquées, layout_weight..etc, plusieurs fois relayout obtiennent la taille exacte. La meilleure solution est d'attendre que le gestionnaire de fenêtres termine le travail, puis d'obtenir une capture d'écran. Essayez de mettre getDrawingCache () dans le gestionnaire.

Kislingk
la source
1

Les réponses de @ cV2 et @ nininho fonctionnent toutes les deux pour moi.

Une des autres raisons pour lesquelles j'ai découvert la manière difficile était que la vue que j'avais générait une vue qui a une largeur et une hauteur de 0 ( c'est-à-dire imaginez avoir un TextView avec un texte de chaîne d'une chaîne vide ). Dans ce cas, getDrawingCache renverra null, alors assurez-vous simplement de vérifier cela. J'espère que cela aide certaines personnes.

Bundeeteddee
la source
1

L'erreur peut être due au fait que votre vue est trop grande pour tenir dans le cache de dessin .

J'ai obtenu l'explication de mon problème "View.getDrawingCache renvoie null" dans mes journaux:

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

La documentation Android indique également : les appareils Android peuvent avoir aussi peu que 16 Mo de mémoire disponible pour une seule application. C'est pourquoi vous ne pouvez pas charger de gros bitmap.

Yuliia Ashomok
la source
1

J'essaye de créer le nombre n d'images dynamiquement basé sur la vue.

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

Je pense que ce code aidera quelqu'un.

Harish
la source
-1

C'est le moyen simple et efficace d'obtenir un 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
la source