Android Lottie使用,如何自定义LottieView?

Lottie

1.简介

最近在做公司项目时候,有涉及到加载动画文件,看到以前的项目使用的是Lottie这个库。

Lottie是一个很多平台都可以用的三方库,按照官网的原话简介如下,这里主要整理记录一下Android端的使用

Lottie 是一个适用于 Android、iOS、Web 和 Windows 的库,它解析 Adobe After Effects 导出的 JSON 格式动画(使用 Bodymovin),并在移动设备和网页上原生渲染它们!

2.使用

话不多说,直接开用。

lottie有指定运行的动画格式:就是json。

2.1导库:

建议用最新版本,因为老版本踩过坑,后面解释

groovy 复制代码
dependencies {
    ...
    implementation "com.airbnb.android:lottie:$lottieVersion"
    ...
}

2.2 LottieAnimationView

LottieAnimationView是最简单、最直接的使用方式,继承自ImageView,可以在xml布局文件里面定义

xml 复制代码
<com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
		
        app:lottie_rawRes="@raw/hello_world" //R.raw
        // or
        app:lottie_fileName="hello_world.json" //assets

        // 循环动画
        app:lottie_loop="true"
        // 加载完成立马动画
        app:lottie_autoPlay="true" />

加载json动画文件的方式主要为以下两种:

  • 在resource目录下的raw目录(⭐)
  • 在assets目录

推荐第一种,可以通过R静态引用资源文件,非常利于管理和访问:

代码层面设置也是ok的,这样更符合实际开发情况,动态加载动画

java 复制代码
lottieAnimationView = findViewById(R.id.lottie);
lottieAnimationView.setAnimation(R.raw.confor);
lottieAnimationView.setRepeatCount(-1);
lottieAnimationView.playAnimation();

lottieview还可以设置静态资源,完全可以当成ImageView来用。

java 复制代码
lottieAnimationView.setImageResource(R.drawable.ic_launcher);
动画回调

想要在动画运行前、后、取消时候进行处理,可以通过回调实现,这个看具体的开发逻辑

java 复制代码
lottieAnimationView.addAnimatorListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(@NonNull Animator animation) {
        lottieAnimationView.setSpeed(-1);//动画开始前设置到放
    }

    @Override
    public void onAnimationEnd(@NonNull Animator animation) {

    }

    @Override
    public void onAnimationCancel(@NonNull Animator animation) {

    }

    @Override
    public void onAnimationRepeat(@NonNull Animator animation) {

    }
});
lottie属性改变

如果想改变动画文件的填充颜色、不透明度、描边宽度等等内容,该怎么办呢,lottie提供了一个addValueCallback方法:

java 复制代码
lottieAnimationView.addValueCallback(
    new KeyPath("**"),
    LottieProperty.COLOR,
    new LottieValueCallback<Integer>(){
        @Nullable
        @Override
        public Integer getValue(LottieFrameInfo frameInfo) {
            return 0xffffff;
        }
    }
);

上图中的例子,主要目的是改变动画文件的颜色,

  • 参数1,keypath是指定要改变的范围,**表示改变所有图层的颜色(这里涉及到分析json文件的格式,就不细讲了,可以参考这篇博文
  • 参数2,传入要改变的属性,例如:STROKE_COLOROPACITY等等。具体可以点进这个类,查看支持哪些属性更改。
  • 参数3,可以通过LottieFrameInfo具体到每一帧是否需要变化,如果不需要做任何处理,直接返回要修改的值即可,这里我对所有帧的颜色做更改。

2.3 LottieDrawable

重头戏!!!!

不知道大家有没有遇到一种情况:需要在自定义view里面实现lottie,这个时候需要在onDraw里面绘制LottieView

lottie官方也提供了可以用于任何view上的LottieDrawable,也是 LottieAnimationView的底层实现

java 复制代码
public class MyLottieView extends View {

    private LottieDrawable lottieDrawable;
    private int mHeight;
    private int mWidth;
    private KeyPath keyPath;
    private LottieValueCallback<Integer> lottieValueCallback;

    public MyLottieView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        lottieDrawable = new LottieDrawable();
        // 异步加载 Lottie JSON(推荐放 res/raw)
        LottieCompositionFactory.fromRawRes(getContext(), R.raw.confor)
            .addListener(comp -> {
                setupComposition(comp, lottieDrawable);
            })
            .addFailureListener(t -> {
                Log.e(TAG, "Lottie load error", t);
            });

        keyPath = new KeyPath("**");
        lottieValueCallback = new LottieValueCallback<>(0xbb191970);
    }

    private void setupComposition(LottieComposition comp, LottieDrawable lottieDrawable) {
        lottieDrawable.setCallback(this);   // 必须:允许 Lottie 触发 invalidate()
        lottieDrawable.setComposition(comp);
        lottieDrawable.addAnimatorUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(@NonNull ValueAnimator animation) {
                invalidate();
            }
        });
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mHeight = getMeasuredHeight();
        mWidth = getMeasuredWidth();
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);

        // 设置绘制区域
        int width = getWidth();
		
        //改变加载出来的动画颜色
        drawable.addValueCallback(
            keyPath,
            LottieProperty.COLOR_FILTER,
            lottieValueCallback
        );

        drawable.setBounds(0, 0, 64, 64);//指定绘制的大小
        drawable.draw(canvas);

    }
}

在自定义view里绘制lottieView还是比较复杂的,上面就是一个简单的例子,可以根据需求,做进一步改动。

下面简单来解析一下上面代码的流程:

  • 首先是初始化一个lottieDrawable,它继承自Drawable
  • 然后是异步加载json动画文件,这一步lottie内部做了异步处理,解析得到的内容是无状态的动画模型------LottieComposition,我们需要在提供的回调内进行下一步处理
  • 将解析得到的json文件加载到lottieDrawable里,并且为lottieDrawable绑定drawable回调,因为我们是支持animattion的drawable。并且设置onAnimationUpdate回调,当动画运行时对每一帧进行绘制
  • 最后就是绘制drawable到屏幕上,绘制方法和原生drawable一样,大家肯定比较熟悉。

!!坑

坑一

如果你的版本小于6.0.0,那么恭喜你,你可能在运行自己写的绘制代码后,lottie并未按照你设定的bounds显示,这是因为这前有bug导致lefttop的设定是不生效的,在这个版本才被修复。所以最好用最新的版本,可以避免很多问题。

坑二

这个问题和json动画文件有关:

原因:因为动画里包含很多图层,每一层都涉及不透明度和颜色,所以如果你修改整个文件的不透明度,那可能会出现动画的镂空部分被加上不透明度,也就是原本透明的地方出现颜色。

这个问题的避免方式,只有在修改的时候自己确定好要修改哪些图层,这个就得了解你json文件的图层结构了。(咱哪有这么多时间来了解这些破结构啊,写个代码还要学你AE导出动画的格式?)

参考:

lottie.airbnb.tech/#/android

juejin.cn/post/712163...

相关推荐
用户4445543654262 小时前
Android依赖的统一管理
前端
南囝coding2 小时前
《独立开发者精选工具》第 025 期
前端·后端
@淡 定2 小时前
Dubbo + Nacos 完整示例项目
前端·chrome·dubbo
毕设源码-邱学长2 小时前
【开题答辩全过程】以 基于web的博客论坛系统的设计与实现为例,包含答辩的问题和答案
前端
就叫曲奇饼干吧2 小时前
前端面试题整理(方便自己看的)
前端·面试
拖拉斯旋风2 小时前
防抖(Debounce)实战解析:如何用闭包优化频繁 AJAX 请求,提升用户体验
前端
bst@微胖子2 小时前
CrewAI+FastAPI实现营销战略协助智能体项目
android·数据库·fastapi
老前端的功夫2 小时前
TypeScript 全局类型声明:declare关键字的深度解析与实战
linux·前端·javascript·ubuntu·typescript·前端框架
golang学习记2 小时前
VS Code 1.107 发布:AI 不再是插件,而是编辑器的「第一大脑」
前端