关于 ink-custom-brush-builder
这项技能指导编码 Agent 使用 Android Ink API 编程创建自定义画笔,涵盖画笔结构、输入响应、纹理及序列化,并说明 `1.1.0-alpha03` 起可用的公开 Kotlin API。
主要功能
- 01BrushFamily 与多涂层结构
- 02触控笔和触摸行为节点树
- 03笔尖几何形状与绘制属性配置
- 04纹理图层与位图存储指导
- 05画笔定义的编码与解码
适用场景
- 01构建压力响应型自定义画笔
- 02创建书法或纹理笔刷
- 03将触控笔倾斜或速度映射为笔刷行为
- 04持久化自定义画笔定义
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ android/ skills --skill ink-custom-brush-builder安装后在 Claude Code 中输入/ink-custom-brush-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/brush-behaviors.mdbrush-structure.mdexamples.mdtextures-and-serialization.mdreferences/android/develop/ui/compose/touch-input/stylus-input/ink-api-brush-apis.md详细介绍
Android Ink API 中的自定义笔刷基于 BrushFamily
层次结构构建:
BrushFamily
├── InputModel (BrushFamily.InputModel.SlidingWindowModel 或 PASSTHROUGH_MODEL)
└── BrushCoat[](一个或多个渲染图层)
├── BrushTip(形状:scaleX、scaleY、cornerRounding、rotationDegrees、slantDegrees、pinch)
│ └── BrushBehavior[](对触控笔或触摸输入的动态响应)
│ └── Tree:TargetNode(input = [Operators](input = SourceNode))
└── BrushPaint(视觉外观)
├── SelfOverlap(ANY、ACCUMULATE 或 DISCARD)
├── TextureLayer[](BrushPaint.TilingTexture 或 BrushPaint.StampingTexture)
└── BrushPaint.ColorFunction[](OpacityMultiplier 或 ReplaceColor)
将自定义 BrushFamily 与 Compose Color、size 和 epsilon 组合,
创建一个 Brush:
val brush = Brush.createWithComposeColor(
family = myCustomFamily,
color = Color.Black,
size = 10f,
epsilon = 0.1f,
)
版本和实验性 API 要求:
- 需要
androidx.ink1.1.0-alpha03或更高版本:在1.0.0(稳定版) 和1.1.0-alpha01-alpha02中,BrushFamily(...)、BrushCoat、BrushTip、BrushPaint、BrushBehavior和androidx.ink.brush.behavior.*节点 均标记为@RestrictTo(LIBRARY_GROUP)(在稳定版1.0.0中,自定义笔刷 只能通过BrushFamily.decode从二进制 proto 流加载)。 从1.1.0-alpha03或更高版本开始,以编程方式创建自定义笔刷的 构造函数已成为公共 API(BrushPaint.TilingTexture、BrushPaint.StampingTexture、BrushPaint.ColorFunction、BrushFamily.InputModel.SlidingWindowModel以及所有行为节点)。1.1.0-alpha03或更高版本无需@OptIn:所有公共自定义笔刷类和ink-storage的BrushFamily序列化 API(BrushFamily.encode和decode、AndroidBrushFamilySerialization、BrushFamilyDecodeCallback)在1.1.0-alpha03或更高版本中均未添加注解(ExperimentalInkCustomBrushApi在1.1.0-alpha05或更高版本中标记为@RestrictTo(LIBRARY_GROUP),且仅在 稳定版1.0.0中序列化BrushFamily时才需要)。
工作流与任务路由
根据请求的自定义笔刷任务,遵循以下条件说明:
- 步骤 1(依赖项):为程序化自定义笔刷设置 Android 项目时,在编辑构建文件前征求用户许可,并确认
gradle/libs.versions.toml和app/build.gradle.kts中的androidx.ink:ink-brush、androidx.ink:ink-brush-compose、androidx.ink:ink-storage和androidx.ink:ink-nativeloader使用的版本为1.1.0-alpha03或更高版本。 - 步骤 2(层级、笔尖形状、绘制效果与输入平滑):定义
BrushFamily和多层涂层BrushCoat、配置BrushTip几何属性(scaleX、scaleY、cornerRounding、rotationDegrees、slantDegrees、pinch)、设置BrushPaint属性(SelfOverlap、ColorFunction),或使用BrushFamily.InputModel.SlidingWindowModel平滑笔画输入时,必须遵循 brush-structure.md。创建基础Brush或加载1.0.0资源时,请参阅 Brush API。 - 步骤 3(动态手写笔和触摸行为):使用
BrushBehavior节点树(SourceNode、DampingNode、NoiseNode、ResponseNode、TargetNode、PolarTargetNode)让笔刷根据手写笔压力、倾斜角度、速度、方向或程序化噪声动态响应时,必须遵循 brush-behaviors.md。 - 步骤 4(纹理与序列化):添加
BrushPaint.TilingTexture或BrushPaint.StampingTexture图层、实现TextureBitmapStore,或编码和解码自定义BrushFamily定义(BrushFamily.encode和decode、AndroidBrushFamilySerialization、BrushFamilyDecodeCallback)时,必须遵循 textures-and-serialization.md。告知用户需要将哪些纹理图像文件(例如app/src/main/res/drawable-nodpi/pencil_grain.png)添加到项目中,并在TextureBitmapStore中注册。 - 步骤 5(完整笔刷配方):从零构建完整的压力感应笔、书法笔尖、阴影铅笔、水彩晕染笔刷或多层涂层阴影笔刷时,请从 examples.md 中可直接复制的实现开始。
- Compose 绘图表面、橡皮擦或持久化:设置 Compose 绘图表面、使用
InProgressStrokes进行湿笔画和干笔画渲染、基于几何形状擦除笔画或使用 Room 持久化笔画时,建议使用ink-app-builder技能。
反模式
- 绝不要使用原始的
ink.proto.*构建器来构造笔刷——始终使用公开的 Kotlin 构造函数(来自androidx.ink.brush.*的BrushFamily、BrushCoat、BrushTip、BrushPaint、BrushBehavior)。 - 绝不要在触摸监听器中手动缩放笔画宽度来实现压力或倾斜角度灵敏度——应使用
BrushBehavior,将SourceNode.Source.NORMALIZED_PRESSURE或TILT_IN_RADIANS映射到TargetNode.Target.SIZE_MULTIPLIER或WIDTH_MULTIPLIER。 - **绝不要使用手动
Canvas位图盖印或BitmapShader**来制作纹理笔刷——应使用带有TextureBitmapStore的BrushPaint.TilingTexture或BrushPaint.StampingTexture。 - 绝不要在最后一个(或唯一一个)
TextureLayer上使用BlendMode.SRC_OVER——应使用BlendMode.MODULATE、DST_IN、DST_OUT、SRC_ATOP或SRC_IN,以避免边缘抗锯齿和OPACITY_MULTIPLIER行为被覆盖。 - 绝不要将
BrushFamily序列化为 JSON、Gson、Moshi 或Parcelable——始终使用BrushFamily.encode和BrushFamily.decode,或使用来自androidx.ink.storage的AndroidBrushFamilySerialization。 - 绝不要手动实现贝塞尔曲线(
quadTo、cubicTo)平滑——应配置BrushFamily.InputModel.SlidingWindowModel来平滑输入,并使用DampingNode来平滑行为。 - **绝不要在绘制循环中使用
Random.nextFloat**来实现有机的笔画抖动——应在BrushBehavior中添加随笔画距离变化的NoiseNode。
评论
支持 Markdown