2010-05-04 8 views
7

¿Cómo puedo anular onDraw para tomar lo que se dibujó (como un mapa de bits) y transformarlo?Anular onDraw para cambiar cómo se produce el dibujo (Android)

El siguiente método funciona, pero desafortunadamente, este método implica la creación de un mapa de bits del tamaño de toda la pantalla, no solo del área que se dibuja. Si uso esto para dibujar elementos UI, se vuelve a dibujar para cada elemento UI. ¿Se puede hacer esto de manera más eficiente?

@Override 
protected void onDraw(Canvas canvas) { 
    //TODO: Reduce the burden from multiple drawing 
    Bitmap bitmap=Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888); 
    Canvas offscreen=new Canvas(bitmap); 
    super.onDraw(offscreen); 
    //Then draw onscreen 
    Paint p=new Paint(); 
    p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); 
    canvas.drawBitmap(bitmap, 0, 0, p); 
} 

Respuesta

7

El siguiente código será mucho más eficiente.

public class MyView extends TextView{ 
    private Canvas offscreen; 

    public MyView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public MyView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public MyView(Context context) { 
     super(context); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     //We want the superclass to draw directly to the offscreen canvas so that we don't get an infinitely deep recursive call 
     if(canvas==offscreen){ 
      super.onDraw(offscreen); 
     } 
     else{ 
      //Our offscreen image uses the dimensions of the view rather than the canvas 
      Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); 
      offscreen=new Canvas(bitmap); 
      super.draw(offscreen); 
      //Create paint to draw effect 
      Paint p=new Paint(); 
      p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); 
      //Draw on the canvas. Fortunately, this class uses relative coordinates so that we don't have to worry about where this View is actually positioned. 
      canvas.drawBitmap(bitmap, 0, 0, p); 
     } 
    } 
} 
+0

¿No se crea demasiada recolección de elementos no utilizados si se crean objetos nuevos en el método de dibujo? – Srin

8

Ha intentado cambiar el tamaño del mapa de bits se crea, ser sólo igual a los límites del clip en lugar de todo el tamaño del lienzo dado? No sé si este es el caso con todas las vistas, pero encontré que el método onDraw para algunas vistas tiene un lienzo tan grande como la pantalla, independientemente del tamaño real del contenido. A continuación, recorta el lienzo, restringiéndolo solo a la esquina superior izquierda, dibuja allí y luego traduce esa parte a otro lugar en la pantalla cuando está realmente lista para mostrar todo el diseño. En otras palabras, a pesar de tener un lienzo del tamaño de toda la pantalla, solo utiliza una pequeña parte de él. Así que lo que podría intentar hacer es en vez de usar

Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), ...) 

podría intentar

Rect rect = canvas.getClipBounds(); 
int width = rect.width(); 
int height = rect.height(); 
Bitmap bitmap = Bitmap.createBitmap(width, height, ...); 

De esta manera se reduce la sobrecarga de trabajo con un mapa de bits mucho más grande de lo necesario. Nota: en realidad no he intentado hacer esto, así que podría no funcionar, pero vale la pena intentarlo.

+0

Creo que el método 'getClipBounds' da las dimensiones correctas, pero dado que no estoy seguro fui con los métodos' getWidth' y 'getHeight' de' View'. Esto no funciona porque el método 'onDraw' usa algún tipo de desplazamiento. Pude resolver esto usando un buen truco con el método 'draw' de' View' que no usa desplazamientos. Sin embargo, tenga en cuenta que los métodos de dibujo de un 'Lienzo' sí usan desplazamientos. Encontré esto confuso al principio, pero todo tiene sentido cuando lo piensas bien. – Casebash

0

me encontré con algo similar, donde canvas.getWidth() y canvas.getHeight() devuelve el ancho y la altura de toda la pantalla en lugar de la vista en sí.

intenta utilizar el siguiente lugar:

Bitmap bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888); 

Para mi caso, getWidth() y getHeight() me devuelve las dimensiones de mi vista. ¡Buena suerte!

Cuestiones relacionadas