APIs de pincel

Las APIs de Brush Ink proporcionan una forma de crear y personalizar pinceles para dibujar en un lienzo.

Cómo crear un pincel

Para crear un pincel, usa los métodos de fábrica Brush con argumentos con nombre, como Brush.createWithColorLong(). Esta clase te permite establecer las siguientes propiedades:

  • family: Es el estilo del pincel, análogo a un tipo de letra o una fuente en el texto. Consulta StockBrushes para ver los valores de BrushFamily disponibles.
  • color: Es el color del pincel. Puedes establecer el color con un ColorLong.
  • size: Es el grosor base de los trazos creados con el pincel.
  • epsilon: Es la distancia más pequeña a la que se deben considerar distintos dos puntos del trazo, lo que controla el nivel de detalle o la fidelidad de la geometría del trazo.
    • Los valores más altos simplifican más el trazo, lo que usa menos memoria y renderiza más rápido, pero puede generar artefactos visibles, como bordes irregulares cuando se acerca el zoom.
    • Los valores más bajos conservan más detalles para el acercamiento de alta calidad, pero aumentan el uso de memoria.
    • Para crear prototipos con una escala de unidades de 1 px, 0.1 es un buen punto de partida. Para las apps de producción que admiten varias densidades de pantalla, usa unidades independientes de la densidad (como dp) y ajusta epsilon según corresponda.
val redBrush = Brush.createWithColorLong(
  family = StockBrushes.pressurePen(),
  colorLong = Color.RED.pack(),
  size = 5F,
  epsilon = 0.1F
)

Cómo modificar las propiedades del pincel

Puedes crear una copia de un pincel existente con el método copy(). Este método te permite cambiar cualquiera de las propiedades del pincel.

val blueBrush = redBrush.copy(colorLong = Color.BLUE.pack())

Pinceles personalizados

Si bien StockBrushes proporciona un conjunto versátil de pinceles comunes, la API de Ink también ofrece una ruta avanzada para crear comportamientos de pincel completamente nuevos para efectos artísticos únicos o para replicar pinceles existentes específicos para la retrocompatibilidad.

Se carga un BrushFamily personalizado desde su formato serializado. El formato requerido es la codificación binaria comprimida con gzip del búfer de protocolo BrushFamily. Esto te permite cargar y usar archivos de pinceles personalizados hoy mismo. Una vez deserializado, el BrushFamily personalizado se puede usar para crear un nuevo Brush con un color y un tamaño específicos, al igual que cualquiera de las familias de StockBrushes.

class CustomBrushes(val context: Context) {

  private const val TAG = "CustomBrushes"

  val brushes by lazy { loadCustomBrushes(context) }

  @OptIn(ExperimentalInkCustomBrushApi::class)
  private fun loadCustomBrushes(): List<CustomBrush> {
    val brushFiles = mapOf(
        "Calligraphy" to (R.raw.calligraphy to R.drawable.draw_24px),
        "Flag Banner" to (R.raw.flag_banner to R.drawable.flag_24px),
        "Graffiti" to (R.raw.graffiti to R.drawable.format_paint_24px),
    // ...
    )

    val loadedBrushes = brushFiles.mapNotNull { (name, pair) ->
      val (resourceId, icon) = pair
      val brushFamily = context.resources.openRawResource(resourceId).use
      { inputStream ->
          BrushFamily.decode(inputStream)
      }
      CustomBrush(name, icon, brushFamily.copy(clientBrushFamilyId = name))     
    }
    return loadedBrushes
  }
}

data class CustomBrush(
  val name: String,
  val icon: Int,
  val brushFamily: BrushFamily
)