前言
Lottie 非常方便,因为它能嵌入设计师使用创作工具制作的动画。在 Android 官方(https://developer.android.com)给的 Compose 动画选型流程图中,对于由多个元素构成的复杂插画动画,也建议使用像 Lottie 这样的框架。
当使用 Lottie 工具制作的动画时,我们有时也希望动态更改其中一部分,比如修改深色/浅色模式,适配夜间主题等。本文将通过示例,介绍如何调整 Lottie 动画内的颜色
示例
首先,准备示例动画。我用 LottieFiles 的 Lottie Creator 制作了一个动画:
直接播放这个动画,效果如下:
@Composable
fun MyAnimation(modifier: Modifier = Modifier) {
val composition by rememberLottieComposition(
spec = LottieCompositionSpec.RawRes(R.raw.my_animation),
)
LottieAnimation(
composition = composition,
modifier = modifier,
iterations = LottieConstants.IterateForever,
)
}
修改颜色
假设在这个动画中,想要动态更改勾选标记圆形的背景色。这种情况下,可以使用 Dynamic Property(动态属性)来进行如下指定:
LottieAnimation(
composition = composition,
modifier = modifier,
iterations = LottieConstants.IterateForever,
dynamicProperties = rememberLottieDynamicProperties(
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = Color.Red.toArgb(),
keyPath = arrayOf("Icon Asset", "Background", "Background", "Fill"),
),
),
)
通过这个更改,圆形的颜色变成了红色:
关于 Dynamic Property,官方文档中有详细说明:
Lottie 文档:
https://airbnb.io
通过 dynamicProperties
,使用 KeyPath(关键路径)指定目标对象,然后更改其值,就能动态修改属性。在这次的例子中,指定的 KeyPath 是 Icon Asset > Background > Background > Fill
这个层级。(后面会介绍 KeyPath 的确定方法)
同样地,如果要更改圆周上移动的进度条的颜色,由于它属于描边而不是填充,所以需要将属性类型指定为 LottieProperty.STROKE_COLOR
,而不是 LottieProperty.COLOR
:
rememberLottieDynamicProperty(
property = LottieProperty.STROKE_COLOR,
value = Color.Red.toArgb(),
keyPath = arrayOf("Progress Track", "Stroke"),
),
最后,对仍然是蓝色的涟漪也进行同样的指定,就完成了:
dynamicProperties = rememberLottieDynamicProperties(
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = Color.Red.toArgb(),
keyPath = arrayOf("Icon Asset", "Background", "Background", "Fill"),
),
rememberLottieDynamicProperty(
property = LottieProperty.STROKE_COLOR,
value = Color.Red.toArgb(),
keyPath = arrayOf("Progress Track", "Stroke"),
),
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = Color.Red.toArgb(),
keyPath = arrayOf("Ripple", "Fill"),
),
),
适配主题
当制定 App 主题时,应当让 Lottie 动画自动适配浅色 / 深色模式
dynamicProperties = rememberLottieDynamicProperties(
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = MaterialTheme.colorScheme.primary.toArgb(),
keyPath = arrayOf("Icon Asset", "Background", "Background", "Fill"),
),
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = MaterialTheme.colorScheme.onPrimary.toArgb(),
keyPath = arrayOf("Icon Asset", "Icon", "Icon", "Fill"),
),
rememberLottieDynamicProperty(
property = LottieProperty.STROKE_COLOR,
value = MaterialTheme.colorScheme.primary.toArgb(),
keyPath = arrayOf("Progress Track", "Stroke"),
),
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = MaterialTheme.colorScheme.primary.toArgb(),
keyPath = arrayOf("Ripple", "Fill"),
),
),
值得一提的是,其实 LottieFiles 自带了主题功能,可以在 JSON 中使用在 slot
里定义的 token。但是操作下来并没有 Dynamic Property 灵活。
修改 Lottie 动画主题:https://lottiefiles.com/blog/working-with-lottie-animations/how-to-add-themes-to-lottie-animations-in-lottie-creator
确定目标 KeyPath 的方法
现在知道了更改颜色的方法,但关键的 KeyPath 要怎么找呢?这其实挺麻烦的,而且它的结构不一定和创作工具中的图层结构一致,理解起来可能有点困难。
这次用 LottieFiles 制作的动画结构如下,但很难一下子从这里想象出 KeyPath:
以这次的情况为例进行说明。我们来找找勾选标记背景圆形填充部分的 KeyPath。理论上打开 JSON 文件,顺着 nm
这个键查找肯定能找到,但 lottie 的 json 文件很长,实际找起来比较麻烦。
可以尝试在命令行中使用 jq
列出一些内容,但很难以层级形式展示:
jq '.. | .nm? | strings' my_animation.json
jq 是一个轻量级、高性能的命令行 JSON 处理工具,主要用于在 Unix-like 系统(如 Linux、macOS)中对 JSON 数据进行解析、过滤、转换和格式化等操作。
另外,因为 KeyPath 可以指定通配符,可以通过不断测试,摸清路径,逐步接近目标:
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = Color.Red.toArgb(),
keyPath = arrayOf("Icon Asset", "**", "Fill"),
)
例如,上面代码,通过指定
keyPath = arrayOf("Icon Asset", "**", "Fill")
,先大致指定了从 Icon Asset
开始,包含其下所有层级中名为 Fill
的元素,先确认这种宽泛的指定能否实现预期的颜色更改效果,然后再根据实际情况进一步调整 KeyPath
,以准确找到需要更改颜色的元素。
还有没有更简便的方法呢? 2025年了,肯定想到借助 AI 了:
AI 提示语:递归扫描 JSON 内的 nm,并基于层级结构显示。
虽然 AI 的准确性并非 100% ,但是即便存在错误,人工也能轻易察觉并进行修正。当然,也可以让 AI 帮忙写一个脚本,通过脚本来查找,往往会更准确。比如下面是我通过 AI 脚本输出的结果