Lottie-Android实战:从入门到精通

张开发
2026/4/20 18:37:34 15 分钟阅读

分享文章

Lottie-Android实战:从入门到精通
1. Lottie-Android基础入门第一次接触Lottie时我被它流畅的动画效果惊艳到了。记得当时项目需要一个复杂的加载动画设计师给了一堆GIF图结果在不同分辨率手机上显示效果参差不齐。直到发现了Lottie这个神器问题才迎刃而解。Lottie是Airbnb开源的一个动画渲染库它能直接解析After Effects制作的动画导出为JSON格式并在Android、iOS等平台原生渲染。这意味着设计师可以用AE做出各种炫酷效果开发者只需简单集成就能完美复现。1.1 快速集成Lottie在Android项目中集成Lottie非常简单。首先在build.gradle中添加依赖dependencies { implementation com.airbnb.android:lottie:5.2.0 // 使用最新稳定版 }然后准备一个JSON动画文件。设计师用AE制作动画后通过Bodymovin插件导出时会生成一个JSON文件描述动画结构可选的images文件夹包含动画用到的图片资源把这些文件放到项目的assets目录下。比如我通常这样组织app/src/main/assets/ ├── lottie/ │ ├── loading.json │ └── success.json └── images/ └── frame_1.png1.2 基础使用方式最简单的使用方式是在XML布局中直接添加LottieAnimationViewcom.airbnb.lottie.LottieAnimationView android:idid/animation_view android:layout_width200dp android:layout_height200dp app:lottie_fileNamelottie/loading.json app:lottie_autoPlaytrue app:lottie_looptrue /几个常用属性说明lottie_fileName指定JSON文件路径lottie_autoPlay是否自动播放lottie_loop是否循环播放lottie_speed播放速度1.0为正常速度在代码中控制动画也很简单val animationView findViewByIdLottieAnimationView(R.id.animation_view) animationView.playAnimation() // 开始播放 animationView.pauseAnimation() // 暂停 animationView.progress 0.5f // 跳转到50%进度2. 进阶功能实战2.1 动态控制动画属性Lottie的强大之处在于可以实时修改动画属性。比如我们要做一个点赞按钮点击时心形填充颜色从灰变红// 找到颜色属性的KeyPath val keyPath KeyPath(**, heart, fill) animationView.addValueCallback(keyPath, LottieProperty.COLOR) { if (isLiked) Color.RED else Color.GRAY }KeyPath的构造参数是图层名称的层级链。如果设计师给的AE文件结构复杂可以用这个技巧查看完整路径animationView.addLottieOnCompositionLoadedListener { it.layers.forEach { layer - Log.d(Lottie, layer.toString()) } }2.2 动态替换资源我们项目有个场景用户完成任务后播放庆祝动画但气球颜色要随机变化。实现方法// 1. 准备不同颜色的气球图片 val balloons listOf(R.drawable.balloon_red, R.drawable.balloon_blue) // 2. 找到要替换的图片ID查看JSON文件中的assets部分 val imageId img_0 // 3. 替换资源 val randomIndex Random.nextInt(balloons.size) animationView.updateBitmap(imageId, BitmapFactory.decodeResource(resources, balloons[randomIndex]))2.3 动画事件监听处理动画关键帧事件非常有用。比如播放到75%时显示奖励弹窗animationView.addAnimatorUpdateListener { if (it.animatedFraction 0.75f !isShown) { showRewardDialog() isShown true } }还可以监听动画状态变化animationView.addAnimatorListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) { // 动画开始 } override fun onAnimationEnd(animation: Animator) { // 动画结束 } })3. 性能优化技巧3.1 内存优化方案在列表中使用Lottie时我发现内存会持续增长。通过分析发现是缓存问题解决方案// 在RecyclerView.Adapter中 override fun onViewRecycled(holder: ViewHolder) { holder.animationView.cancelAnimation() holder.animationView.setComposition(null) }对于复杂的动画建议开启硬件加速com.airbnb.lottie.LottieAnimationView ... android:layerTypehardware /3.2 网络动画加载从网络加载Lottie动画的推荐做法val cacheKey premium_animation // 唯一缓存key LottieCompositionFactory.fromUrl(this, https://example.com/anim.json, cacheKey) .addListener { composition - animationView.setComposition(composition) animationView.playAnimation() }记得添加网络权限并处理加载状态和错误情况。3.3 尺寸适配策略设计师给的动画尺寸可能不适合所有设备我常用这些适配方案保持宽高比缩放app:lottie_scale0.5 !-- 整体缩放50% --代码动态计算缩放比例val maxScale min( screenWidth / composition.bounds.width(), screenHeight / composition.bounds.height() ) animationView.scale maxScale.coerceAtMost(1f) // 不超过原始尺寸4. 高级应用场景4.1 与RecyclerView的联动在电商项目中我实现过商品列表的加入购物车动画。当点击商品时图标会飞向底部购物车准备两个版本的Lottie JSON静态图标idle.json飞行动画fly.json点击时切换动画fun startAddToCartAnimation(view: View, target: View) { val animationView LottieAnimationView(context).apply { setAnimation(fly.json) layoutParams LayoutParams(48.dp, 48.dp) addView(this) } // 计算起始和结束位置 val startPos IntArray(2) view.getLocationOnScreen(startPos) val endPos IntArray(2) target.getLocationOnScreen(endPos) // 创建位移动画 val animator ObjectAnimator.ofFloat(animationView, translationX, startPos[0], endPos[0]) animator.duration 800 animator.start() }4.2 动画组合播放实现多段动画无缝衔接的技巧val anim1 LottieAnimationView(context).apply { setAnimation(part1.json) addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { startAnimation(anim2) } }) } val anim2 LottieAnimationView(context).apply { setAnimation(part2.json) } fun startAnimation() { anim1.playAnimation() }4.3 动态修改文本对于包含文本的动画可以实时更新内容val textDelegate object : TextDelegate(animationView) { override fun getText(input: String): String { return when(input) { placeholder_name - userName placeholder_date - currentDate else - input } } } animationView.setTextDelegate(textDelegate)记得让设计师在AE中给文本图层命名这些名称会出现在JSON文件中。

更多文章