Brush API

Brush API 为您提供了定义笔画视觉样式的工具。您可以创建具有不同颜色、大小和系列的画笔,以实现各种外观。

创建笔刷

如需创建画笔,请使用 Compose Brush 伴生方法和命名实参(例如 Brush.Companion.createWithComposeColor)。 此类可让您设置以下属性:

  • family:笔刷的样式,类似于文本中的字样或字体。 如需了解可用的 BrushFamily 值,请参阅 StockBrushes。
  • color:画笔的颜色。您可以使用 ColorLong 设置颜色。
  • size:使用画笔创建的笔画的整体粗细。
  • epsilon:为了生成笔画几何图形,两个点在视觉上应被视为不同的最小距离。epsilon 与笔画点数的比率控制着笔画在不产生伪影的情况下可以放大多少,但会消耗内存。描边单位的理想起点是 1 px,epsilon 的理想起点是 0.1。epsilon 值越高,使用的内存越少,但在出现三角形伪影之前允许的缩放比例越小。通过实验找到适合您应用场景的值。

val brush = Brush.createWithComposeColor(
    family = StockBrushes.pressurePen(),
    color = Color.Black,
    size = 5F,
    epsilon = 0.1F
)

修改画笔属性

您可以使用 copyWithComposeColor() 方法创建现有画笔的副本,以便更改画笔的任何属性。

val redBrush = Brush.createWithComposeColor(
    family = StockBrushes.pressurePen(),
    color = Color.Red,
    size = 5F,
    epsilon = 0.1F
)

val blueBrush = redBrush.copyWithComposeColor(color = Color.Blue)

自定义画笔

While StockBrushes provides a versatile set of common brushes, Ink API also offers an advanced path for creating entirely new brush behaviors for unique artistic effects or to replicate specific existing brushes for backward compatibility.

A custom BrushFamily is loaded from its serialized format. The required format is the gzipped binary encoding of the BrushFamily protocol buffer. This lets you load and use custom brush files today. Once deserialized, the custom BrushFamily can be used to create a new Brush with a specific color and size, just like any of the StockBrushes families.

class CustomBrushes(val context: Context) {

    companion object {
        private const val TAG = "CustomBrushes"
    }

    val brushes by lazy { loadCustomBrushes() }

    @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)
        }
        return loadedBrushes
    }
}

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