Antialiasing de lienzo con aceleración de hardware (Android API 11 y posterior)
Tengo un mapa de bits simple que dibujo dentro de un lienzo y que rota con una matriz.
El problema que encuentro es que usando la aceleración de hardware los bordes no son anti-alias cuando se gira (esto está funcionando perfectamente con la aceleración de hardware apagar). Y por supuesto cosas como "setDrawFilter" son inútiles ya que son ignorados cuando la aceleración de hardware está activada!
- ¿Qué es lo que hace Bitmap # recycle () en Android Honeycomb?
- Honeycomb Android emulador es perro lento - se manejará antes del lanzamiento oficial?
- Configuración del tema holográfico en Honeycomb
- Estrategias para Honeycomb y compatibilidad con versiones anteriores
- Fragmentos onResume de la pila trasera
canvas.setDrawFilter(new PaintFlagsDrawFilter(1, Paint.ANTI_ALIAS_FLAG));
¿Estoy perdiendo algo o es sólo una limitación del método de renderizado de hardware? ¿Hay alguna alternativa?
- ¿Cómo puedo atenuar la barra del sistema en Android 3.0 (Honeycomb)?
- Reproducción de Honeycomb GMail UI con fragmentos
- TextView setScaleX () / setScaleY () y setTextIsSelectable (true) selección
- Habilitar la aceleración de hardware en la aplicación para Android, dirigida a Honeycomb AND versiones anteriores
- ¿Cómo implementar el botón de retroceso de Android ActionBar?
- Campo de intención del calendario Título / descripción no funciona en Motorola Xoom Honeycomb 3.1 y Acer Iconia
- Fragmentos método onClick en el elemento fragmento
- Botón de menú de nido de abeja objetivo
Poner la bandera antialias en la pintura no ayudaría de todos modos. Para obtener bordes antialiased en el mapa de bits al girarlos, debe agregar un borde transparente 1px alrededor de ellos.
La adición de este borde transparente 1px no es tan fácil como pensé. Agregarlo en tiempo de ejecución es realmente complicado. Mi aplicación carga un montón de mapa de bits y para agregar este borde necesito asignar aún más mapa de bits para volver a dibujarlos. Esto realmente busto el montón, pero como he tenido mucho cuidado con evitar cualquier pérdida de memoria, está funcionando como se pretende. Lo que realmente me está matando son los "retrasos" que esto ha introducido. Busqué esta fluidez perdida para el GC. Este último parece estar ralentizando el hilo de interfaz de usuario cuando reclama de nuevo los mapas de bits reciclados. Usar una memoria caché tampoco es la solución. Este es el mejor camino hacia el rendimiento, pero el almacenamiento de 500×500 PNGs (alpha obliged) es muy desproporcionado. Entonces, aquí estoy, golpeando la pared. Todavía no he probado un "tiempo de sorteo", pero mi conjetura es que el dibujo de un buffer de mapa de bits fuera de pantalla que no creo que será HW acc. (Corregirme si estoy equivocado) no ayudará a mi causa.
La idea de tener un "shader AA" es realmente seductora y veo aquí varias ventajas. Está bien soportado por la aceleración de hardware, por supuesto será una maravilla para la memoria (no más salvaje asignación de mapa de bits) y podría ser totalmente independiente de la escala de mapa de bits. Hice una prueba rápida y esto es, con mucho, el mejor AA (y aquí quiero decir en calidad) que logro obtener y … es rápido … Esta rápida conclusión hacer un borde superior AA usando shaders.
BitmapShader bitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP); Matrix m = new Matrix(); m.postTranslate(0, 1); bitmapShader.setLocalMatrix(m); final LinearGradient AAshader = new LinearGradient(0, 0, 0, 1, 0x00000000, 0xffffffff, TileMode.CLAMP); ComposeShader compositor = new ComposeShader(bitmapShader, AAshader, PorterDuff.Mode.DST_IN); mPaint.setShader(compositor); canvas.drawRect(this.getBounds(), mPaint);
Ahora el gran inconveniente! Cómo obtener un 4 de borde AA 🙂 ??? Probablemente podemos manejar un borde superior / inferior AA usando un gradiente de pasos múltiples, pero esto todavía está sucio. Una buena manera será combinar el mapa de bits de origen con algún tipo de 9 parches para obtener la frontera transparente, pero no podemos componer 2 bitmapShader … Así que, aquí estoy una vez más. Cómo obtener esta máscara Shader! Maldita pared
Solución que funcionó en mi caso:
private void fixAntiAlias(View viewFromThe80s) { if (Build.VERSION.SDK_INT > 10) { Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG); viewFromThe80s.setLayerType(View.LAYER_TYPE_SOFTWARE, p); ((View) viewFromThe80s.getParent()).setLayerType(View.LAYER_TYPE_SOFTWARE, p); } }
Detalles:
Mi vista de texto utiliza un parche de 9 como fondo, así que no pude agregar un borde transparente de 1px sin afectar a los píxeles de 9 parches. Por lo tanto, en su lugar, pude conseguir este trabajo desactivando la aceleración de hardware para la vista dada y su padre:
Estoy llamando a esto justo después de ver la inflación. Específicamente en onCreateViewHolder
en mi caso (en el constructor de visor para ser exactos). Esto corrige mi roturado TextView que utiliza un fondo NinePatchDrawable, similar a lo siguiente:
<TextView android:id="@+id/text_new_feature" android:layout_height="wrap_content" android:layout_width="wrap_content" android:rotation="-30" android:background="@drawable/background_new_feature"/>