Android View.getDrawingCache devuelve nulo, solo nulo


97

¿Alguien podría intentar explicarme por qué?

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

SIEMPRE registra que la caché de dibujo es nula y establece el mapa de bits en nulo?

¿Tengo que dibujar la vista antes de configurar la caché?

¡Gracias!


1
stackoverflow.com/questions/9791714/… evitar usar el getDrawingCache()uso View#drawpara Canvasacercarse
Yuraj

Respuestas:


240

También estaba teniendo este problema y encontré esta respuesta:

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 medida de WebView depende del tamaño del contenido, por lo que si la página web aún no está cargada, obtendrá una medida de 0. Intente pasar el tamaño real para medir en lugar de UNSPECIFIED como MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
Todavía devuelve nulo incluso con MeasureSpec.EXACTLY.

En una vista lo suficientemente grande, esto no funcionó para mí. (Posiblemente porque tengo un teléfono con recursos de memoria muy limitados). La respuesta a continuación de cV2 funcionó bien para mí.
Simon Forsberg

@nininho ¿cómo se puede dibujar desde imageview sin usar el método getdrawingchache ()?
Gorgeous_DroidVirus

Funciona bien. Pero afecta en UI. Ayúdanos a resolver este problema.
Vivek Ravi

58

si getDrawingCachesiempre es returning nullchicos: usa esto:

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

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


1
Buena. Este funcionó para mí mientras que los demás no. ¿Hay alguna razón para usar los valores de en getLayoutParamslugar de v.getWidth () y v.getHeight ()?
Simon Forsberg

lo siento, personalmente, no puedo ayudarlo con su pregunta: '(-> agradable que haya funcionado :)
cV2

@ cV2 obtuve el dibujo en las imágenes, pero necesito obtener el getdrawingcache en la ejecución de surfaceview ... entonces, ¿qué puedo hacer a continuación?
Gorgeous_DroidVirus

4
obtengo la excepción de ancho y alto debe ser> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Ver vista = ScreenShotActivity.this.findViewById (R.id.relativelayout); Mapa de bits mapa de bits = loadBitmapFromView (ver);}}
akash yadav

2
Creo que el `ancho y alto de excepción deben ser> 0` se produce cuando ImageViewaún no ha recibido una imagen, por lo que parece ser 0. Esto se desarrollaría de manera diferente para el código de diferentes personas, pero asegúrese de que su llamada a loadBitmapFromView()sea ​​definitivamente posterior tu ImageViewcontiene una imagen.
Azurespot

6

La razón básica por la que se obtienen valores nulos es que la vista no está dimensionada. Entonces, todos los intentos, usando view.getWidth (), view.getLayoutParams (). Width, etc., incluyendo view.getDrawingCache () y view.buildDrawingCache (), son inútiles. Por lo tanto, primero debe establecer las dimensiones de la vista, por ejemplo:

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

(Ya ha configurado 'ancho' y 'alto' como desee u obtenido con WindowManager, etc.)


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

4

Estoy usando esto en su lugar.

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

3

Trabaja mejor 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

Si la vista que desea capturar realmente se muestra en la pantalla, pero devuelve nulo. Eso significa que captura la vista antes de que el Administrador de ventanas la genere. Algunos diseños son muy complicados. Si el diseño incluye diseños anidados, layout_weight..etc, hace que varias veces la retransmisión obtenga el tamaño exacto. La mejor solución es esperar hasta que el administrador de ventanas termine el trabajo y luego obtener una captura de pantalla. Intente poner getDrawingCache () en el controlador.


1

Las respuestas de @ cV2 y @ nininho funcionan para mí.

Una de las otras razones por las que descubrí por las malas fue que la vista que tenía estaba generando una vista que tiene un ancho y un alto de 0 ( es decir, imagina tener un TextView con una cadena de texto de una cadena vacía ). En este caso, getDrawingCache devolverá un valor nulo, así que asegúrese de verificarlo. Espero que ayude a algunas personas.


1

El error puede deberse a que su Vista es demasiado grande para caber en la memoria caché de dibujos .

Obtuve la explicación de mi problema "View.getDrawingCache devuelve nulo" de mis registros:

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

Android docs también dice : Los dispositivos Android pueden tener tan solo 16 MB de memoria disponible para una sola aplicación. Es por eso que no puede cargar mapas de bits grandes.


1

Estoy tratando de crear el número n de imágenes dinámicamente según la vista.

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

Creo que este código ayudará a alguien ...


-1

Esta es la forma simple y eficiente de obtener mapas de bits.

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();
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.