Brush API는 획의 시각적 스타일을 정의하는 도구를 제공합니다. 다양한 색상, 크기, 계열의 브러시를 만들어 다양한 디자인을 구현할 수 있습니다.
Android 기술
GitHub에서 보기맞춤 잉크 브러시 만들기
ink-custom-brush-builder Android 기술을 사용하여 Jetpack Compose에서 맞춤 팁, 동적 동작, 질감, 코팅으로 맞춤 BrushFamily 스타일을 디자인합니다.android skills add ink-custom-brush-builder브러시 만들기
브러시를 만들려면 Brush.Companion.createWithComposeColor와 같은 이름이 지정된 인수가 있는 Compose Brush 도우미 메서드를 사용합니다.
이 클래스를 사용하면 다음 속성을 설정할 수 있습니다.
family: 브러시 스타일로, 텍스트의 서체 또는 글꼴과 유사합니다. 사용 가능한BrushFamily값은StockBrushes을 참조하세요.color: 브러시 색상입니다.ColorLong를 사용하여 색상을 설정할 수 있습니다.size: 브러시로 만든 획의 전체 두께입니다.epsilon: 획 생성 도형 목적으로 두 점이 시각적으로 구별되는 것으로 간주되어야 하는 가장 작은 거리입니다. 입실론과 획 포인트의 비율은 메모리를 희생하면서 아티팩트 없이 획을 얼마나 확대할 수 있는지를 제어합니다. 획 단위의 적절한 시작점은 1px이고 입실론의 적절한 시작점은 0.1입니다. 엡실론 값이 높을수록 메모리를 적게 사용하지만 삼각형 아티팩트가 표시되기 전에 확대/축소가 줄어듭니다. 사용 사례에 적합한 값을 찾기 위해 실험합니다.
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)
맞춤 브러시
StockBrushes는 다양한 일반 브러시를 제공하지만, Ink API는 독특한 예술적 효과를 위한 완전히 새로운 브러시 동작을 만들거나 이전 버전과의 호환성을 위해 기존의 특정 브러시를 복제하는 고급 경로도 제공합니다.
커스텀 BrushFamily가 직렬화된 형식에서 로드됩니다. 필수 형식은 BrushFamily 프로토콜 버퍼의 gzip으로 압축된 바이너리 인코딩입니다. 이를 통해 지금 바로 커스텀 브러시 파일을 로드하고 사용할 수 있습니다. 역직렬화되면 맞춤 BrushFamily를 사용하여 StockBrushes 계열과 마찬가지로 특정 색상과 크기의 새 Brush를 만들 수 있습니다.
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 )