Android View.getDrawingCache retorna nulo, apenas nulo


97

Alguém poderia tentar me explicar por que

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 que o cache de desenho é nulo e define o bitmap como nulo?

Devo realmente desenhar a visualização antes que o cache seja definido?

Obrigado!


1
stackoverflow.com/questions/9791714/… evitar o getDrawingCache()uso View#drawde Canvasabordagem
Yuraj

Respostas:


240

Eu também estava tendo esse problema e encontrei esta resposta:

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
A medição do WebView depende do tamanho do conteúdo, portanto, se a página da web ainda não foi carregada, você obterá uma medida de 0. Tente passar o tamanho real para medir em vez de NÃO ESPECIFICADO como MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
Ainda retorna nulo mesmo com MeasureSpec.EXACTLY.

Em uma visão grande o suficiente, isso não funcionou para mim. (Possivelmente porque tenho um telefone com recursos de memória muito limitados). A resposta abaixo da cV2 funcionou bem para mim.
Simon Forsberg

@nininho como obter drawable a partir de imageview sem usar o método getdrawingchache ()?
Gorgeous_DroidVirus

Isso funciona bem. Mas isso afeta na IU. Por favor, ajude a resolver este problema.
Vivek Ravi,

58

se getDrawingCacheé sempre returning nullcaras: use isto:

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

Referência: https://stackoverflow.com/a/6272951/371749


1
Um bom. Este funcionou para mim enquanto os outros não. Há algum motivo para usar os valores de em getLayoutParamsvez de v.getWidth () e v.getHeight ()?
Simon Forsberg

desculpe, pessoalmente, não posso ajudá-lo com sua pergunta: '(-> bom que funcionou :)
cV2

@ cV2 consegui o desenho nas imagens, mas preciso pegar o getdrawingcache ao rodar o surfaceview ... então o que posso fazer a seguir?
Gorgeous_DroidVirus

4
estou recebendo exceção de largura e altura deve ser> 0 .............................. 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
Acho que a `largura e altura da exceção devem ser> 0` ocorre quando você ImageViewainda não recebeu uma imagem, então parece ser 0. Isso funcionaria de forma diferente para o código de pessoas diferentes, mas certifique-se de que sua chamada para loadBitmapFromView()é definitivamente depois seu ImageViewcontém uma imagem.
Azurespot

6

O motivo básico para obtermos nulos é que a visualização não é dimensionada. Todas as tentativas, então, usando view.getWidth (), view.getLayoutParams (). Width, etc., incluindo view.getDrawingCache () e view.buildDrawingCache (), são inúteis. Portanto, você precisa primeiro definir as dimensões da vista, por exemplo:

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

(Você já definiu 'largura' e 'altura' como gostaria ou os obteve com WindowManager, etc.)


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

4

Estou usando isso.

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

3

Trabalhe melhor 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 a visualização que você deseja capturar realmente aparece na tela, mas retorna nulo. Isso significa que você captura a visualização antes que o gerenciador de janelas a gere. Alguns layouts são muito complicados. Se o layout inclui layouts aninhados, layout_weight..etc, ele faz com que o relayout obtenha o tamanho exato várias vezes. A melhor solução é esperar até que o gerenciador de janelas termine o trabalho e então obter a captura de tela. Tente colocar getDrawingCache () no manipulador.


1

As respostas de @ cV2 e @ nininho funcionam para mim.

Um dos outros motivos pelos quais descobri da maneira mais difícil é que a visualização que eu tinha gerava uma visualização com largura e altura 0 ( ou seja, imagine ter um TextView com um texto de string de uma string vazia ). Nesse caso, getDrawingCache retornará null, portanto, certifique-se de verificar isso. Espero que ajude algumas pessoas por aí.


1

O erro pode ser porque sua visualização é muito grande para caber no cache de desenho .

Recebi a explicação do meu problema "View.getDrawingCache retorna null" em meus registros:

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

A documentação do Android também diz : Os dispositivos Android podem ter até 16 MB de memória disponível para um único aplicativo. É por isso que você não pode carregar um bitmap grande.


1

Estou tentando criar o número n de imagens dinamicamente com base no modo de exibição.

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

Acho que esse código vai ajudar alguém ..


-1

Esta é a maneira simples e eficiente de obter 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();
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.