学会在Jetpack Compose中加载Lottie动画资源

本文译自「From File to Fetch」,原文链接proandroiddev.com/from-file-t...,由Katie Barnett发布于2025年11月23日。

注意 :我与 Airbnb 及其Lottie 项目(Lottie 的 GitHub 仓库)没有任何关联。 我最近刚在一个应用中实现了 Lottie,想分享一些示例来佐证官方文档

了解 Lottie

之前,我写过关于动画的文章medium.com/bilue/card-...,也上讨论过这个主题,以及我是如何创建原生动画的。但有时,我们想要一些更具艺术性的效果,不需要移动屏幕上的可组合元素;这时,我们就需要一个预先构建好的动画。

Lottie 就派上用场了。

如果你之前没有使用过 Lottie,它是由 Airbnb 开发人员开发的一个库,可以解析 Adob​​e After Effects 动画并将其导出为 JSON 格式。其理念是,设计师可以创建复杂的动画,而无需手动渲染。有很多设计工具的插件可以帮助创建动画,例如 Figma。如果你具备一定的设计天赋(我没有!),上手也很容易。

Lottie 已经存在一段时间了,可以在多个平台上渲染,例如 iOS、Web、Windows,当然还有 Android。它可用于 XML 视图,但我今天要重点介绍的是它与 Jetpack Compose 的集成。

官方文档在这里 lottie.airbnb.tech/#/android-c...,但它并没有详细介绍如何使用 LottieCompositionSpec 中的多种不同源类​​型,以最便捷的方式提供我们的 Lottie 文件。实际上,某些应用可能需要处理多种源类型,尤其是在后端调用中指定特定动画的情况下。

我们将逐步介绍每种类型,但首先,让我们使用字符串来保存 Lottie 动画数据,从而进行基本设置。

字符串来源

使用任何 SDK 的第一步都是添加依赖项:

kotlin 复制代码
// build.gradle.kts
...

dependencies {
    ...
    implementation(libs.lottie.compose)
}

// libs.version.toml
[versions]
lottie = "6.6.6"

[libraries]
lottie-compose = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie" }

然后,在 Composable 中,我们需要创建 LottieCompositionSpec。对于 JSON 字符串,我们可以使用 LottieCompositionSpec.JsonString(val jsonString: String)

并将字符串传递给它。接下来,使用 rememberLottieComposition 并传入 spec 来记住组合状态。最后,可以将此状态传递给 LottieAnimation 以显示动画。

kotlin 复制代码
val lottieCompositionSpec = LottieCompositionSpec.JsonString(JSON_STRING)
val lottieComposition = rememberLottieComposition(
    spec = lottieCompositionSpec
)
LottieAnimation(composition = lottieComposition.value)

const val JSON_STRING = "{\"v\":\"4.10.1\",...\"bm\":0}]}"

现在,将动画存储在字符串中并非最易读或可持续的方式,更好的选择是使用Lottie JSON文件。一种方法是将其存储在assets目录中......

Asset文件

我们可以将Lottie文件存储为.json.lottie文件(它们是同一种文件,只是扩展名不同),并将其存储在app/assets目录中。

这里唯一的区别是我们需要使用 LottieCompositionSpec.Asset(val assetName: String) 并传递 assets 目录下的路径(你可以根据需要进行组织)。

kotlin 复制代码
val lottieCompositionSpecLottieFile = LottieCompositionSpec.Asset("animations/android_wave.lottie")
val lottieCompositionSpecJsonFile = LottieCompositionSpec.Asset("animations/android_wave.json")

类似地,我们可以使用 LottieCompositionSpec.File(val fileName: String) 从设备文件系统中的任何位置加载动画文件------只需确保应用程序已获得该文件的访问权限即可!

使用资源文件意味着我们无法获得编译时保护来确保文件存在,但我们可以使用 res/raw 目录。

原始资源文件

同样,这很简单,只需将文件添加到 raw 目录即可:

现在,我们可以通过使用 LottieCompositionSpec.RawResR.raw 访问原始资源,从而获得编译时安全性。

kotlin 复制代码
val lottieCompositionSpec = LottieCompositionSpec.RawRes(R.raw.android_wave)

最后,如果我们希望在需要时动态获取 Lottie 文件,而不是将其打包到应用程序中,我们可以从 URL 加载它。

URL 来源

与上述类似,我们可以使用 LottieCompositionSpec.Url 加载以 URL 形式存储的 Lottie 文件:

kotlin 复制代码
val lottieCompositionSpec = LottieCompositionSpec.Url("https://url/AndroidWave.json")

如果一切顺利,用户网络连接良好,这当然很好,但我们需要确保能够处理任何错误。

错误响应和添加加载状态

动画加载也可能需要一些时间,尤其是在动画文件较大或用户网络连接不佳的情况下。为此,我们可以使用 LottieCompositionResult 来检测动画的状态。

当动画正在下载或解析时,LottieCompositionResult.isLoading 将为 true;当解析成功且合成已准备好显示时,LottieCompositionResult.isSuccess 将为 true。我们还有两个状态:LottieCompositionResult.isComplete,当 isLoading 为 false 时(无论组合是否成功),它将为 true;最后是 LottieCompositionResult.isFailure,当出现不可恢复的错误时(即下文讨论的 onRetry lambda 返回 false 时),它将为 true。

为了展示标准的加载、错误和成功行为,我们可以像这样使用 isLoadingisSuccess

kotlin 复制代码
if (lottieComposition.isLoading) {
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier.height(100.dp)
    ) {
        CircularProgressIndicator()
    }
} else if (lottieComposition.isSuccess) {
    LottieAnimation(
        composition = lottieComposition.value,
        modifier = Modifier.height(100.dp)
    )
} else {
    Image(
        imageVector = Icons.Filled.Error,
        contentDescription = null,
        modifier = Modifier.height(100.dp)
    )
}

重试动画加载错误

Lottie 提供了一种简单易用的方法,可以使用 rememberLottieComposition 中的 onRetry 来重试动画加载。我们可以通过两种方式使用它:

反复重试直到达到某个限制

在构造 rememberLottieComposition 时,我们可以指定 onRetry lambda,并返回 true 以继续重试,返回 false 以停止重试。 onRetry 包含一个 failCount 参数。这允许应用重试次数限制或指数退避。例如:

kotlin 复制代码
val lottieComposition = rememberLottieComposition(
    spec = lottieCompositionSpec,
    onRetry = { failCount, exception ->
        Timber.d(exception, "Error loading animation: ${exception.message}")
        failCount < 5
    }
)

这里我将动画设置为重试 5 次后停止。你可以在此 lambda 表达式中添加错误消息或其他任何有用的信息(但请使用上面描述的 LottieCompositionResult.isLoading 布尔值来显示加载行为,而不是在此处设置另一个变量)。

等待重试信号

我们还可以允许动画等待重试,直到某个外部条件发生变化,例如按下按钮或恢复网络连接。

为此,我们使用 rememberLottieRetrySignal

kotlin 复制代码
val retrySignal = rememberLottieRetrySignal()
var url by remember { mutableStateOf("https://bad/url") }
val lottieCompositionSpec = LottieCompositionSpec.Url(url)
val lottieComposition = rememberLottieComposition(
    spec = lottieCompositionSpec,
    onRetry = { _, exception ->
        Timber.d(exception, "Error loading animation: ${exception.message}")
        retrySignal.awaitRetry()
        false
    }
)
Column(...) {
    if (lottieComposition.isLoading) {
        ...
    } else if (lottieComposition.isSuccess) {
        LottieAnimation(
            composition = lottieComposition.value,
            modifier = Modifier.height(100.dp)
        )
    } else {
        ...
    }
    TextButton(onClick = {
        url = "https://url/AndroidWave.json"
        retrySignal.retry()
    }) {
        Text("Fix url & retry")
    }
}

在这个简单的示例中,我将 URL 设置为无效 URL,然后在 onRetry 中,当发生错误时,我们可以使用记住的 retrySignal 来等待重试。 retrySignal.awaitRetry()。动画将保持加载状态,直到按钮点击时调用 retrySignal.retry()。如果你不希望保持加载状态,而是希望在重试之前显示错误信息,你可以完全省略 retrySignal,并更新已记住的 url 状态,这样 LottieCompositionSpec 将重新组合。

动画配置

最后,动画加载正确后,我们可以使用一些其他配置项来优化动画效果。

虽然最好在 Lottie 文件本身(创建时完成)中控制这些动画行为,但你也可以通过以下方式调整动画的播放方式: LottieAnimation 本身是可组合的。要了解其功能,最好查看一些可用参数:

kotlin 复制代码
// An excerpt from version 6.6.6 of the SDK
@Composable
fun LottieAnimation(
    clipSpec: LottieClipSpec? = null,
    speed: Float = 1f,
    iterations: Int = 1,
    reverseOnRepeat: Boolean = false,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    ... // + others for more advanced use, check out the SDK documentation
) {}

在这里,我们可以控制:

  • clipSpec:动画播放的帧

  • speed:动画速度

  • iterations:动画运行次数(使用 LottieConstants.IterateForever 可无限循环)

  • reverseOnRepeat:循环播放后反向播放

  • alignmentcontentScale:就像图像一样,我们可以调整动画在指定范围内的布局。

现在你可以了解 Lottie 的所有用法,请务必为你正在开发的应用程序选择最佳方案,并选择最便捷的方式从你的设计团队获取文件,而无需费力地在不同文件格式之间进行转换。

再见!现在!

你可以在我的 GitHub 仓库的 jc-lottie 模块中找到上述示例代码。

欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!

保护原创,请勿转载!

相关推荐
summerkissyou19873 小时前
Android-Camera-为啥不移到packages/module
android·相机
liang_jy3 小时前
Android UID
android·面试
nono牛6 小时前
安卓/MTK平台日志关键词详解
android
TimeFine7 小时前
Android AI解放生产力(四)实战:解放绘制UI的繁琐工作
android
sheji34167 小时前
【开题答辩全过程】以 基于Android的社区车位共享管理系统的设计与实现为例,包含答辩的问题和答案
android
TimeFine7 小时前
Android AI解放生产力(三):认识custom_prompts和skills
android
summerkissyou19878 小时前
Android-Audio-为啥不移到packages/module
android·音视频
catchadmin8 小时前
PHP 值对象实战指南:避免原始类型偏执
android·开发语言·php
BoomHe8 小时前
Android 键盘事件导致页面产生「 半透明蒙层」
android