Lottie 动画在项目中的使用总结

Lottie 动画在项目中的使用总结

1.背景

基于 lottie 动画高频使用用法,总结 lottie 动画在项目中的使用技巧及注意事项,便于以后在项目中处理类似需求快速检索入运用,后期会不定期完善,欢迎补充及指正不足之处。

2. Lottie 是什么?

Lottie 是一个同时支持 Android 、 iOS 、React Native 、Web 和 Windows 设备的一个开源动画框架。

用户只要先用 Adobe After Effects 软件做出动画,再将动画文件通过 Bodymovin 导出为 json 文件,就可以通过 Lottie 来解析这些 json 文件实现动画了。

前端开发人员,只需要拿到 UI (动效)同学给的 json 文件 即可实现 动效的 百分之百的还原,简单高效。

3. Lottie 核心类

Lottie 提供一个 LottieAnimationView 给用户使用,而实际 Lottie 的核心是 LottieDrawable,它承载了所有的绘制工作,LottieAnimationView 则是对 LottieDrawable 的封装,再附加了一些例如解析的功能。

  • LottieComposition 是对应的 Model,承载所有信息。
  • CompositionLayer 是 layer 的集合。
  • ImageAssetBitmapManager 负责管理动画所需的图片资源。
  • LottieAnimationView 用户加载 Lottie 动画的默认和最简单的方式(直接使用)

lottie

4. 使用步骤

​ 开源地址:https://github.com/airbnb/lottie-android

  1. 添加依赖
dependencies {
  implementation 'com.airbnb.android:lottie:$lottieVersion'
}

截至目前,最新版本为:5.0.3

  1. 在布局 xml 中使用:
<com.airbnb.lottie.LottieAnimationView
        android:id="@+id/lottieAnimationView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:lottie_fileName="hello-world.json"
        app:lottie_loop="true"
        app:lottie_rawRes="@raw/heart"
        app:lottie_imageAssetsFolder="images"
        app:lottie_autoPlay="true"

注意: 这里的 app:lottie_rawResapp:lottie_fileName 这两个属性是一样的。

上图 xml 里面的 @raw/heart是一个 json 文件,Lottie 是通过解析 json 文件去实现的。

LottieAnimationView animationView = ... 
animationView.setAnimation(R.raw.hello_world); 
// or 
animationView.setAnimation(R.raw.hello_world.json); 
animationView.playAnimation();
  1. 控制动画添加动画监听
lottieAnimationView.addAnimatorUpdateListener((animation) -> {
    // 动画状态监听回调
});
lottieAnimationView.playAnimation(); // 播放动画
...
if (lottieAnimationView.isAnimating()) { // 动画正在运行
}
...
// progress 范围 0 ~ 1f,设置动画进度
lottieAnimationView.setProgress(0.5f);
...
// 自定义动画时长,此处利用 ValueAnimator 值动画来实时更新 AnimationView 的进度来达到控制动画时长。
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f)
    .setDuration(500);
animator.addUpdateListener(animation -> {
    lottieAnimationView.setProgress(animation.getAnimatedValue());
});
animator.start();  // 启动动画
...
lottieAnimationView.cancelAnimation();// 取消动画

因此,可以随意控制动画的时常,动画的播放进度,动画的各种状态等

  1. 常用方法:
方法功能
setAnimation(int)设置播放动画的 json 文件名称
setAnimation(int, CacheStrategy)设置播放动画的 json 文件资源和缓存策略
loop(boolean)设置动画是否循环(默认为false)
setRepeatMode(int)设置动画的重复模式(默认为restart)
setRepeatCount(int)设置动画的重复次数(默认为-1)
lottie_cacheStrategy设置动画的缓存策略(默认为weak)
lottie_colorFilter设置动画的着色颜色(优先级最低)
setScale(float)设置动画的比例(默认为1f)
setProgress(float)设置动画的播放进度
setImageAssetsFolder(String)设置动画依赖的图片资源文件地址
playAnimation()从头开始播放动画
pauseAnimation()暂停播放动画
resumeAnimation()继续从当前位置播放动画
cancelAnimation()取消播放动画
  1. 监听动画进度 [0,1]
   lottieAnimationView.addAnimatorUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            // 判断动画加载结束
            if (valueAnimator.getAnimatedFraction() == 1f) {
            }
        }
    });
  1. 循环/播放某个部分
lottieAnimationView.loop(true);
// 播放动画的某个部分
setMinFrame(...)
setMaxFrame(...)
setMinProgress(...)
setMaxProgress(...)
setMinAndMaxFrame(...)
setMinAndMaxProgress(...)
	4. 获取动画的时长
// 比如获取 UI 给的动画(lottie_count_down)素材时长  
val lottieComposition: LottieComposition = LottieCompositionFactory.fromRawResSync(
                context,
                R.raw.lottie_count_down
            ).value!!
Log.d(TAG, "lottieComposition.duration : ${lottieComposition.duration} ")  //  得到 6000ms

5. 使用注意事项

1. 控制 Lottie 动画执行的速度和时间

Lottie 动画,在导出成 JSON 之后,其实动画执行的速度和时长,都是已经固定了的。所以如果想要修改这两个参数,除了麻烦设计师使用 After Effects 重新修改之后再导出之外,还可以使用 ValueAniamtor 配合 setProgress() 方法来实现。

2. Lottie 的缓存策略

应用程序中可能会有一些经常使用的动画,比如加载动画等等。为了避免每次加载文件和发序列化的开销,你可以在你的动画上设置一个缓存策略。在 setAnimation() APIs都可以采用可选的第二个参数 CacheStrategy

在默认情况下,Lottie 将保存对动画的弱引用,这对于大多数情况来说应该足够了。

但是,如果确定某个动画肯定会经常使用,那么请将其缓存策略更改为 CacheStrategy.Strong
或者如果确定某个动画很大而且不会经常使用,把缓存策略改成 CacheStrategy.None

CacheStrategy 可以是NoneWeakStrong 三种形式来让 LottieAnimationView 对加载和解析动画的使用强或弱引用的方式。弱或强表示缓存中组合的 GC 引用强度。

6. 在项目中使用示例

需求场景:

用户播放倒计时视频时,根据播放的视频时长,同步实现水平进度条的圆滑动效。

开发实现思路:

​ 根据 UI 提供的动画(count_down.json)素材,计算不同时长的播放进度和速度。

   <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/lottieCountDownTime"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        app:lottie_fileName="lottie/count_down.json" />

关键思路

var mRestPastTime = 0L
private var countDownDuration: Long = 60L
fun start() {
        lottieCountDownTime.removeUpdateListener(mRestLottieAnimatorUpdateListener)
        lottieCountDownTime.cancelAnimation()
        mRestPastTime = 0L
        lottieCountDownTime.apply {
            val lottieComposition: LottieComposition = LottieCompositionFactory.fromRawResSync(
                context,
                R.raw.lottie_count_down
            ).value!!

            mRestLottieAnimatorUpdateListener = ValueAnimator.AnimatorUpdateListener { animation ->
                mRestPastTime = (countDownDuration * animation.animatedFraction).toLong()
                Log.d(TAG, "lottieComposition.duration : ${lottieComposition.duration} ")  // 5016ms
                countDownTime = countDownDuration - mRestPastTime
                val leftTime = (countDownTime / 1000).toString()
                Log.d(TAG, "leftTime:$leftTime ")  // 59 ~ 0 s
                setRestTimeText(countDownDuration - mRestPastTime, false)
                if (animation.animatedFraction >= 1) {
                    //播放结束处理
                }
            }
            setComposition(lottieComposition)
            progress = 0f
            //核心点:根据时长控制播放的进度
            speed = lottieComposition.duration / countDownDuration
            playAnimation()
            addAnimatorUpdateListener(mRestLottieAnimatorUpdateListener)
        }
    }

根据上述的使用示例,实现了 UI 给的水平进度条动效,非常圆滑的实现,并且滑动进度可以根据不同的时长来一一对应进度,在倒计时场景中,用户如果在播放视频时反复暂停和开启动操作,我们还得处理一下,进度和到计时状态同步的问题。此处用 lottie 动画来实现,只需要调用暂停(pauseAnimation)和恢复(resumeAnimation)即可。

其他实现思路1:

如果用属性动画来实现的话,可能会出现不同圆滑或有卡顿的情况。

用属性动画使用示例:

/**
     * 设置 ProgressBar 的进度(平滑的增长)
     * @param progressBar progressBar
     * @param progressTo 取值 0 - 100 在 10 倍的时间内平滑 效果更平滑
     */
    private fun setProgressSmooth(progressBar: ProgressBar, progressTo: Int) {
        val animator = ObjectAnimator.ofInt(
            progressBar, "progress",
            progressBar.progress,
            progressTo * 10
        )
        animator?.apply {
            duration = 300
            // 匀速绘制
            interpolator = LinearInterpolator()
            start()
        }
    }
  <ProgressBar
        android:id="@+id/countDownPb"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:max="1000"
        android:progressDrawable="@drawable/pb_pd_bg"
        tools:progress="500" />

注: 其中 pb_pd_bg.xml 中背景图的实现

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 进度条背景色 -->
    <item android:id="@android:id/background">
        <shape>
            <solid android:color="@color/black" />
        </shape>
    </item>
    <!--  第二进度条 -->
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <solid android:color="@color/blue" />
            </shape>
        </clip>
    </item>
</layer-list>

此处,android:max="1000"设置为 1000,这一点需要注意,平时开发中,我们一般设置为 100,这里是新的思路。在进度刷新时放大 10 倍,再结合属性动画的 LinearInterpolator特性,基本也能实现 水平圆滑的效果,不过在用户反复暂停或恢复倒计时,由于属性动画绘制时间duration的原因,不会立即停止,会有延迟暂停的卡顿感。

其他开发思路2:

可以用自定义 View 的思路实现,OnDraw 刷新时去同步进度。如何倒计时如果不想圆滑的效果,就 1s 更新 1次进度,

想圆滑进度的话,就 10ms 更新 1次。不过需要处理倒计时的暂停、恢复等业务逻辑。

综上,总结两种使用方法,在实际开发中,根据不同的使用场景选择。按目前的资源及动效要求,用 lottile 最简单最高效。

(后面有时间会进一步总结: 圆形倒计时中的圆滑进度实现 和实现倒计时的几种方式及场景运用)

7. FQA

一、如何快速预览设计师的 lottie 动画?

  1. UI 设计师提供 Demo 及 动效 Json+ HTML 文件 。点开HTML 文件即可预览。
  2. 在线预览 https://lottiefiles.com/private/animations(可以多个预览切换) 注册登录后,直接把 xx.json 动效文件拖到界面预览。部分白色的动效可能看不到,最好和设计师确定一下。
    2022.3.25 更新 直接在线预览 不用注册
    Lottie tools
    似乎比上面官方的好用。

二、 加载卡顿的问题

待补充

三、设置进度的问题

setMinAndMaxProgress(0.5f, 1f)

设置进度后:这里的 speed 会加速

四、 lottie 动画大小设置

由于 lottie 的底层为 ImageView,参考类似属性始可解决。

如,设置:

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/countDownPb"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        app:lottie_fileName="lottie/lottie_horizontal_progress.json" />

lottie_horizontal_progress.json中的大小可能不会铺满 match_parent,需要设置:android:scaleType="fitXY"

这里需要注意一下适配器,如果 UI 给的动效本身就是按固定尺寸来设计的,这里就不要设置这个属性了,否则会出现位置错乱的问题。

8. 未来方向

可能会用 PAG 取代 lottie

从解码渲染层面对比 PAG 与 lottie

9. 参考资料

lottie-android : github.com/airbnb/lott…

Introducing Lottie: medium.com/airbnb-engi…

design-lottie: airbnb.design/lottie/

bodymovin: github.com/bodymovin/b…

Animation: Jump-through: medium.com/google-deve…

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android,可以使用Lottie库来加载和播放Lottie动画。以下是一些常见的控制Lottie动画的方法: 1. 播放和停止动画 可以使用`playAnimation()`方法来播放动画使用`cancelAnimation()`方法来停止动画。 ```java LottieAnimationView animationView = findViewById(R.id.animation_view); animationView.playAnimation(); // 播放动画 animationView.cancelAnimation(); // 停止动画 ``` 2. 循环播放动画 可以使用`setRepeatCount()`方法来设置动画的循环次数,使用`setRepeatMode()`方法来设置动画的循环模式。 ```java LottieAnimationView animationView = findViewById(R.id.animation_view); animationView.setRepeatCount(LottieDrawable.INFINITE); // 设置无限循环 animationView.setRepeatMode(LottieDrawable.RESTART); // 设置循环模式为重新开始 ``` 3. 动态改变动画速度 可以使用`setSpeed()`方法来设置动画的速度。默认速度为1.0,可以设置为小于1.0的值来减慢速度,或者大于1.0的值来加快速度。 ```java LottieAnimationView animationView = findViewById(R.id.animation_view); animationView.setSpeed(0.5f); // 设置动画速度为原速度的一半 ``` 4. 动画监听器 可以使用`addAnimatorListener()`方法来添加动画监听器,监听动画的各种事件,例如动画开始、结束、重复等。 ```java LottieAnimationView animationView = findViewById(R.id.animation_view); animationView.addAnimatorListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { // 动画开始时执行的操作 } @Override public void onAnimationEnd(Animator animation) { // 动画结束时执行的操作 } @Override public void onAnimationCancel(Animator animation) { // 动画被取消时执行的操作 } @Override public void onAnimationRepeat(Animator animation) { // 动画重复时执行的操作 } }); ``` 这些方法可以帮助你在Android控制Lottie动画,让你的应用更加生动有趣。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小羊子说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值