用途
这个技能用于在 Jetpack Compose 中为标签文字实现“高光扫过”效果:一段高亮沿着字形移动,看起来像光线扫过文字。与常见做法不同的是,它不覆盖矩形、不复制文字做遮罩,而是直接把可动画的 Brush 设置到 TextStyle 上,由画笔绘制字形本身。因此不需要测量标签宽度,在任何宽度、任何语言、换行与否的情况下都能工作。
主要能力
- 通过
TextStyle.copy(brush = Brush.horizontalGradient(...))给文字设置渐变前景。 - 用
rememberInfiniteTransition和animateFloat驱动渐变的startX/endX,让高光从左到右循环扫过。 - 文档给出完整代码片段:用
head * (span * 3f) - span计算 x,使渐变带在扫过前完全位于文字左侧、扫过后完全位于右侧;中间色停靠点使用纯白色(浅色背景上可用纯黑色),两端使用标签颜色降低透明度。 - 说明
TileMode.Clamp能在渐变带之外保持最近的颜色停靠点,使标签其余部分看起来正常。
使用方式
- 在显示标签的组合项外部声明无限过渡(例如
rememberInfiniteTransition),只对实际绘制标签的部分做条件渲染(如AnimatedVisibility)。 - 在
Text的 style 中通过copy(brush = ...)设置水平渐变,并让startX/endX随动画值变化。 - 根据密度把 dp 转换为像素,避免硬编码像素在不同设备上效果不一致。
- 若在列表中,把单个过渡提升到列表之上并向下传值,防止每行各自重启。
适用场景
- 短暂出现的状态提示文字(如“处理中”),需要视觉上的扫光提示。
- 需要在任意宽度和语言下保持一致的文本高光动画。
- 不想为文本高光做尺寸测量或遮罩复制的界面。
限制与注意
- 文档明确指出动画必须无条件声明,否则标签每次出现都会从零重启,高光会跳回左边缘。
- 高光中间色必须是纯白或纯黑,不能用标签自身颜色调亮,否则在自适应灰色上几乎不可见。
- 设置 Brush 后文字颜色被替换而非着色,
copy的 brush 重载没有color参数,静止外观完全由渐变两端决定。 startX/endX是文字布局空间中的像素,硬编码数值在不同密度设备上宽度不同;需在调用点用LocalDensity转换。- 不要用
Text(color = …)的平色动画代替,因为平色动画会让所有字形同时变亮,看起来像闪烁。 - 文档另附验证命令(grep 与 javap),用于检查动画声明位置和 Brush 前景是否还有颜色可覆盖。