2010-06-01 10 views
14

Tengo una vista personalizada que llena mi pantalla completa. (Un teclado de piano) Cuando un usuario toca la tecla, hace que se llame a invalidate() y se vuelve a dibujar todo el teclado para mostrar el nuevo estado con una tecla tocada.Android: ¿Cómo obtener una vista personalizada para volver a dibujar parcialmente?

Actualmente la vista es muy simple, pero planeo agregar gráficos un poco más agradables. Dado que todo el teclado se procesa dinámicamente, esto haría que redibujar todo el teclado sea más caro.

Así que pensé, veamos el redibujado parcial. Ahora llamo al invalidate(Rect dirty) con la región sucia correcta. Configuré el método onDraw(Canvas canvas) para dibujar las claves en la región sucia solo si realmente quiero un redibujado parcial. Esto hace que esas teclas se dibujen, pero el resto del teclado está totalmente negro/no dibujado.

¿Me equivoco al esperar que al llamar al invalidate(Rect dirty) se "guarde en caché" el canvas actual, y solo "permita" dibujar en la región sucia?

¿Hay alguna manera de que pueda lograr lo que quiero? (Una manera de "caché" el lienzo y sólo volver a dibujar la zona sucia "

Respuesta

18

buena solución actual es almacenar en caché manualmente el lienzo completo a un mapa de bits:?

private void onDraw(Canvas canvas) 
{ 
    if (!initialDrawingIsPerformed) 
    { 
      this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), 
      Config.ARGB_8888); //Change to lower bitmap config if possible. 
      Canvas cacheCanvas = new Canvas(this.cachedBitmap); 
      doInitialDrawing(cacheCanvas); 
      canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint()); 
      initialDrawingIsPerformed = true; 
    } 
    else 
    { 
      canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint()); 
      doPartialRedraws(canvas); 
    } 
} 

Por supuesto, es necesario almacenar la información acerca de qué volver a dibujar y preferiblemente no utilizar un nuevo Paint cada vez, pero que son detalles.

También tenga en cuenta: Los mapas de bits son bastante pesados ​​en el uso de memoria de su aplicación. Tuve bloqueos cuando guardé en caché una vista que se utilizó con un scroller y que era como 5 veces la altura del dispositivo, ya que usaba> 10MB de memoria!

+1

Hmm, no me gusta este solutnio porque la razón por la que sus teclas están parcialmente dibujadas es porque primero debería tener un dibujo completo de hiscanvas de todos modos. Por lo tanto, la pregunta es por qué su lienzo no dibujó correctamente en primer lugar. –

+1

Tengo que tener en cuenta que ahora entiendo que cuando llamas 'invalidate' con un' rect' sucio, puedes simplemente usar tu código de dibujo normal, y solo debería realizar las operaciones de dibujo que están en el 'rect' sucio. 'Canvas' descarta las operaciones que están fuera del' rect'. Aún así, esto significa que gran parte de tu propio código aún se procesa y en mis pruebas con aceleración HW fue más lento que simplemente renderizar la vista por completo. – Peterdk

+1

Tenga en cuenta que para dibujar mapas de bits en lienzo, el parámetro de pintura puede ser nulo, p. 'canvas.drawBitmap (mapa de bits, 0, 0, nulo)'. – greg7gkb

5

Para complementar la respuesta de Peterdk, puede guardar sus operaciones en una imagen en lugar de un mapa de bits.

  • un mapa de bits ahorrará todos los píxeles, como le dijo que podría tomar una gran cantidad de memoria.
  • Una imagen se guardará el llamadas, como drawRect, drawLine, etc.

Depende de lo que es realmente pesado en su aplicación: una gran cantidad de extracciones, unos pocos dibujar operaciones, pero controlada por cálculos pesados , un montón de espacio en blanco/sin usar (prefiera la imagen) etc ...

+0

¡Bien, investigará esto! – Peterdk

+0

Disculpe. ¿Grabará 'Picture'' drawBitmap (bitmap) 'llamadas? Probablemente no, ¿verdad? – Yeung

+0

Tenga en cuenta que la reproducción de imágenes solo se admite en lienzos de software, por lo que no puede usar capas de hardware para las vistas que usan esto. – greg7gkb

Cuestiones relacionadas