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!

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?

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"/> 
  • ¿Hay una manera de mostrar fragmentos en TabHost?
  • Fragmento de carga de hiladora / diálogo en Honeycomb
  • Android Crea una acción personalizada SearchView Search
  • Panal y cursores (frustrado)
  • ¿Se incluirá la nueva API de ActionBar en el backport Fragment?
  • La palabra @drawable no está correctamente escrita
  • Cargadores de Android, el camino a seguir?
  • La animación de transición de fragmentos personalizada no se reproduce correctamente cuando hago estallar el BackStack
  • Utilice diferentes colores para diferentes ActionBar.Tab
  • Android Fragmentos y animación
  • ¿Sólo una aplicación en una pestaña de galaxias?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.