Brush API

Brush API 提供多種工具,可定義筆劃的視覺樣式。您可以建立不同顏色、大小和系列的筆刷,打造各種外觀。

建立筆刷

如要建立筆刷,請使用 Compose Brush 隨附方法和具名引數,例如 Brush.Companion.createWithComposeColor。 這個類別可讓您設定下列屬性:

  • family:筆刷的樣式,類似於文字中的字體或字型。如要查看可用的 BrushFamily 值,請參閱 StockBrushes
  • color:筆刷顏色。您可以使用 ColorLong 設定顏色。
  • size:使用筆刷建立的筆觸整體粗細。
  • epsilon:兩個點之間的最短距離,如果小於這個距離,系統會視為視覺上不同的點,用於生成筆劃幾何圖形。epsilon 和筆劃點的比率會控制筆劃可放大的程度,但會耗用記憶體。筆觸單位的合適起點為 1 像素,epsilon 的合適起點為 0.1。epsilon 值越高,使用的記憶體越少,但出現三角形構件前允許的縮放程度越小。請進行實驗,找出適合您用途的值。
val brush = Brush.createWithComposeColor(
  family = StockBrushes.pressure(),
  colorIntArgb = Color.Black,
  size = 5F,
  epsilon = 0.1F
)

修改筆刷屬性

您可以使用 copyWithComposeColor() 方法建立現有筆刷的副本,藉此變更筆刷的任何屬性。

val redBrush = Brush.createWithComposeColor(
  family = StockBrushes.pressurePen(),
  colorIntArgb = 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) {

  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
)