Android 动画 Lottie 如何使用

Android 动画 Lottie 如何使用

一、简介

Lottie 是Airbnb开源的一个面向 iOS、Android、React Native 的动画库,能分析 Adobe After Effects 导出的动画,并且能让原生 App 像使用静态素材一样使用这些动画,完美实现动画效果。

二、Lottie动画文件制作

1.让设计师使用Adobe 的 After Effects(简称 AE)工具(美工一般都会这个)制作这个动画。

2.在AE中安装一个叫做Bodymovin的插件。下载 bodymovin,解压缩后只需要\build\extension\bodymovin.zxp这个档案就可以

3.手动安装plugin,以windows系统而言,要先下载 **ExMan Command Line tool **并解压缩。 再来把下载的bodymovin压缩后的 bodymovin-master\build\extension 目录下的bodymovin.zxp 这个档案复制进去同一个资料夹。

4.去找cmd,并以系统管理员身分执行。

5.打“cd C:/ExManCmd_win 所在的路径“,进入ExManCmd的资料夹中

6.接着打 ExManCmd.exe /install bodymovin.zxp 就完

7.再来进入AE 后,可以在windows/extentions/bodymovin 找到插件,开启后按下Render 就完成了。 重点来了,这时会在你选的Destination Folder目录中生成一个json格式的文件,这个 json 文件描述了该动画的一些关键点的坐标以及运动轨迹。

三、如何使用Lottie

Lottie支持多平台,使用同一个JSON动画文件,可在不同平台实现相同的效果。支持Android,ios,前段。

1.依赖

在项目的 build.gradle 文件添加依赖

dependencies {  
  compile 'com.airbnb.android:lottie:2.1.0'
}

2.动画文件

第一种方法,将我们所需要的动画文件loading.json保存在app/src/main/assets文件里。 第二种方法,网络上AE生成的动画文件。

3.使用

在布局文件中使用

<com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="400dp"
        android:layout_height="400dp"
        app:lottie_fileName="loading.json"
        app:lottie_loop="true"
        app:lottie_autoPlay="true"/>

使用网络加载AE生成的动画文件json

private void loadUrl(String url) {
    client.newCall(request).enqueue(new Callback() {
        @Override 
        public void onFailure(Call call, IOException e) {

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {
                try {
                    JSONObject json = new JSONObject(response.body().string());
                    LottieComposition.Factory
                            .fromJson(getResources(), json, new OnCompositionLoadedListener() {
                                @Override
                                public void onCompositionLoaded(LottieComposition composition) {
                                    setComposition(composition);
                                }
                            });
                } catch (JSONException e) {
                }
            }
        }
    });
}

private  void setComposition(LottieComposition composition){
    animation_view.setProgress(0);
    animation_view.loop(true);
    animation_view.setComposition(composition);
    animation_view.playAnimation();
}

四、Lottie实现原理

设计师把一张复杂的图片使用多个图层来表示,每个图层展示一部分内容,图层中的内容也可以拆分为多个元素。拆分元素之后,根据动画需求,可以单独对图层或者图层中的元素做平移、旋转、收缩等动画。

Lottie的使用的资源是需要先通过bodymovin( bodymovin 插件本身是用于网页上呈现各种AE效果的一个开源库)将 Adobe After Effects (AE)生成的aep动画工程文件转换为通用的json格式描述文件。Lottie则负责解析动画的数据,计算每个动画在某个时间点的状态,准确地绘制到屏幕上。

Lottie主要类图:

Lottie对外通过控件LottieAnimationView暴露接口,控制动画。

LottieAnimationView继承自ImageView,通过当前时间绘制canvas显示到界面上。这里有两个关键类:LottieComposition 负责解析json描述文件,把json内容转成Java数据对象;LottieDrawable负责绘制,把LottieComposition转成的数据对象绘制成drawable显示到View上。顺序如下:

解析json外部结构LottieComposition封装整个动画的信息,包括动画大小,动画时长,帧率,用到的图片,字体,图层等等。

{
    "v": "4.6.0",               //bodymovin的版本
    "fr": 29.9700012207031,     //帧率
    "ip": 0,                    //起始关键帧
    "op": 141.000005743048,     //结束关键帧
    "w": 800,                   //动画宽度
    "h": 800,                   //动画高度
    "ddd": 0, 
    "assets": [...]             //资源信息
    "layers": [...]             //图层信息
}

解析图片资源

"assets": [                 //资源信息
    {                       //第一张图片
        "id": "image_0",    //图片id
        "w": 58,            //图片宽度
        "h": 31,            //图片高度
        "u": "images/",     //图片路径
        "p": "img_0.png"    //图片名称
    },
    {...}                   //第n张图片
]

解析图层

"layers": [                 //图层信息
    {                       //第一层动画
        "ddd": 0, 
        "ind": 0,           //layer id 图层 id
        "ty": 4,            //图层类型
        "nm": "center_circle", 
        "ks": {...},        //动画
        "ao": 0, 
        "shapes": [...], 
        "ip": 0,            //inFrame 该图层起始关键帧
        "op": 90,           //outFrame 该图层结束关键帧
        "st": 0,            //startFrame 开始
        "bm": 0, 
        "sr": 1
    }, 
    {...}                   //第n层动画
]

如何动起来时序图

利用属性动画控制进度,每次进度改变通知到每一层,触发LottieAnimationView重绘。代码如下:

public LottieDrawable() {
    animator.setRepeatCount(0);
    animator.setInterpolator(new LinearInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            if (systemAnimationsAreDisabled) {
                animator.cancel();
                setProgress(1f);
            } else {
                setProgress((float) animation.getAnimatedValue());
            }
        }
    });
}

通过CompositionLayer把进度传递到各个图层

@Override
public void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
    super.setProgress(progress);
    if (timeRemapping != null) {
        long duration = lottieDrawable.getComposition().getDuration();
        long remappedTime = (long) (timeRemapping.getValue() * 1000);
        progress = remappedTime / (float) duration;
    }
    if (layerModel.getTimeStretch() != 0) {
        progress /= layerModel.getTimeStretch();
    }
    progress -= layerModel.getStartProgress();
    for (int i = layers.size() - 1; i >= 0; i--) {
        layers.get(i).setProgress(progress);
    }
}

通知进度改变

void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
    if (progress < getStartDelayProgress()) {
      progress = 0f;
    } else if (progress > getEndProgress()) {
      progress = 1f;
    }

    if (progress == this.progress) {
      return;
    }
    this.progress = progress;

    for (int i = 0; i < listeners.size(); i++) {
      listeners.get(i).onValueChanged();
    }
  }

最终回调到LottieAnimationView的invalidateDrawable

@Override
public void invalidateDrawable(@NonNull Drawable dr) {
    if (getDrawable() == lottieDrawable) {
      // We always want to invalidate the root drawable so it redraws the whole drawable.
      // Eventually it would be great to be able to invalidate just the changed region.
        super.invalidateDrawable(lottieDrawable);
    } else {
      // Otherwise work as regular ImageView
        super.invalidateDrawable(dr);
    }
}

最后触发LottieDrawable重绘

@Override
public void draw(@NonNull Canvas canvas) {
    ...
    matrix.reset();
    matrix.preScale(scale, scale);
    compositionLayer.draw(canvas, matrix, alpha);   //这里会调用所有layer的绘制方法
    if (hasExtraScale) {
        canvas.restore();
    }
}

总结

1.劣势
(1)性能不够好—某些动画特效,内存和性能不够好;相对于属性动画,在展示大动画时,帧率较低


2.优势
(1)开发效率高—代码实现简单,更换动画方便,易于调试和维护。
(2)数据源多样性—可从assets,sdcard,网络加载动画资源,能做到不发版本,动态更新
(3)跨平台—设计稿导出一份动画描述文件,android,ios,react native通用
(4) Lottie使用简单,易于上手,非常值得尝试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/243369.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RRC下的NAS层

无线资源控制&#xff08;Radio Resource Control&#xff0c;RRC&#xff09;&#xff0c;又称为无线资源管理&#xff08;RRM&#xff09;或者无线资源分配&#xff08;RRA&#xff09;&#xff0c;是指通过一定的策略和手段进行无线资源管理、控制和调度&#xff0c;在满足服…

12.13_黑马数据结构与算法笔记Java

目录 098 堆 heapify 3 099 堆 增删替换 100 堆 e01 堆排序 100 堆e02 求数组第k大元素 100 堆e03 求数据流第k大元素 100 堆e04 求数据流中位数1 100 堆e04 求数据流中位数2 100 堆e04 求数据流中位数3 101 二叉树 概述 102 二叉树 深度优先遍历 103 二叉树 前中后…

人工智能导论习题集(2)

第三章&#xff1a;确定性推理 题1题2题3题4题5题6 题1 题2 题3 题4 题5 题6

Docker容器:docker推送镜像至Harbor

目录 1、Harbor创建项目 2、进入test项目&#xff0c;查看推送命令 3、在docker服务器上准备一个镜像 4、修改docker客户端配置 5、重启docker服务 6、docker登录Harbor 7、docker镜像推送到Harbor 1、Harbor创建项目 2、进入test项目&#xff0c;查看推送命令 3、在dock…

薅github的羊毛-用pages建自己的博客或资源站 - 博客工具 - 2/2

笔者调研了好多个静态博客工具&#xff0c;最后锁定Hexo了&#xff0c;但不等于其他博客不行。我只吐槽两个 Hugo - 难用Gridea - 简直就是骗钱的&#xff0c;我交钱用不了 theme没有链接&#xff0c;同步也同步不了&#xff0c;估计以前是可以&#xff0c;现在经营不下去&…

JUC并发编程 04——Java内存模型之JMM

一.CPU 缓存模型 为什么要弄一个 CPU 高速缓存呢&#xff1f; 类比我们开发网站后台系统使用的缓存&#xff08;比如 Redis&#xff09;是为了解决程序处理速度和访问常规关系型数据库速度不对等的问题。 CPU 缓存则是为了解决 CPU 处理速度和内存处理速度不对等的问题。 我们…

MDK 生成二进制bin文件 设置 任意路径

第一步&#xff1a;找到魔法&#xff0c; 第二步&#xff1a;拷贝语法到Run#1 : fromelf.exe --bin -o "$LL.bin" "#L" 第三步&#xff1a;点击Ok 第四步&#xff1a;重新编译即可生成bin文件

自炫锁2-b

1. 自旋锁 自旋锁也是为实现保护共享资源而提出一种锁机制。其实&#xff0c;自旋锁与互斥锁比较类似&#xff0c;它们都是为了解决对某项资源的互斥使用。 无论是互斥锁&#xff0c;还是自旋锁&#xff0c;在任何时刻&#xff0c;最多只能有一个保持者&#xff0c;也就说&…

CGAL的3D网格生成

1、介绍 该软件包致力于生成离散三维域的各向同性简化网格。要网格化的域是三维空间的子集&#xff0c;需要有界。域可以连接或由多个组件组成和/或细分为几个子域。 边界曲面和细分曲面是平滑曲面或分段平滑曲面&#xff0c;由平面或曲面面片形成。表面可能表现出一维特征&…

TCP/IP详解——ARP 协议

文章目录 一、ARP 协议1. ARP 数据包格式2. ARP 工作过程3. ARP 缓存4. ARP 请求5. ARP 响应6. ARP 代理7. ARP 探测IP冲突8. ARP 协议抓包分析9. ARP 断网攻击10. 总结 一、ARP 协议 ARP&#xff08;Address Resolution Protocol&#xff09;协议工作在网络层和数据链路层之间…

浅谈 USB Bulk 深入浅出 (3) - USB Bulk 装置传输的注意事项

来源&#xff1a;大大通 作者&#xff1a;冷氣團 1 USB Bulk 是什么 USB 是即插即用使用差动信号的装置界面&#xff0c;是以 端点 ( Endpoint )&#xff0c;做为传输装置的输出入端&#xff0c;透过不同的端点 ( Endpoint ) 和模式&#xff0c;来进行与装置的沟通&#xff…

WWW 指南-万维网联盟(World Wide Web)

WWW - 万维网联盟 WWW通常称为网络。 web是一个世界各地的计算机网络。 电脑在Web上使用标准语言沟通。 万维网联盟&#xff08;W3C&#xff09;制定了Web标准 什么是WWW&#xff1f; WWW 代表 World Wide Web(万维网)万维网常常被称为 网络网络是世界各地的计算机网络网络中…

nestjs守卫/全局守卫校验jwt

一、守卫 目标 部分接口需要用户登录后才可以访问&#xff0c;用户登录后可以颁发 jwt_token 给前端&#xff0c;前端在调用需要鉴权的接口&#xff0c;需要在请求头添加 jwt_token&#xff0c;后端校验通过才能继续访问&#xff0c;否则返回403无权访问 创建守卫 anth 安装…

java.lang.NegativeArraySizeException

构建maven项目时发生的异常 maven-resources-production:gci-system-start:java.lang.NegativeArraySizeException:-1972174848解决方案 先将 target 目录删除,然后重新构建项目即可

【从零开始学习JVM | 第九篇】了解 常见垃圾回收器

前言&#xff1a; 垃圾回收器&#xff08;Garbage Collector&#xff09;是现代编程语言中的一项重要技术&#xff0c;它提供了自动内存管理的机制&#xff0c;极大地简化了开发人员对内存分配和释放的繁琐工作。通过垃圾回收器&#xff0c;我们能够更高效地利用计算机的内存资…

基于pandoraNext使用chatgpt4

1.登陆GitHub 获取pandoraNext项目GitHub - pandora-next/deploy: Pandora Cloud Pandora Server Shared Chat BackendAPI Proxy Chat2API Signup Free PandoraNext. New GPTs(Gizmo) UI, All in one! 在release中选择相应版本操作系统的安装包进行下载 2.获取license_…

【OS】操作系统总复习笔记

操作系统总复习 文章目录 操作系统总复习一、考试题型1. 论述分析题2. 计算题3. 应用题 二、操作系统引论&#xff08;第1章&#xff09;2.1 操作系统的发展过程2.2 操作系统定义2.3 操作系统的基本特性2.3.1 并发2.3.2 共享2.3.3 虚拟2.3.4 异步 2.4 OS的功能2.5 OS结构2.5 习…

聊聊Java中的常用类String

String、StringBuffer、StringBuilder 的区别 从可变性分析 String不可变。StringBuffer、StringBuilder都继承自AbstractStringBuilder &#xff0c;两者的底层的数组value并没有使用private和final修饰&#xff0c;所以是可变的。 AbstractStringBuilder 源码如下所示 ab…

鸿蒙ArkTS Web组件加载空白的问题原因及解决方案

问题症状 初学鸿蒙开发&#xff0c;按照官方文档Web组件文档《使用Web组件加载页面》示例中的代码照抄运行后显示空白&#xff0c;纠结之余多方搜索后扔无解决方法。 运行代码 import web_webview from ohos.web.webviewEntry Component struct Index {controller: web_webv…

MuMu模拟器12如何连接adb?

一、MuMu模拟器12端口查看 MuMu模拟器12现已支持adb同时连接多个模拟器进行调试的操作&#xff0c;可以参考以下步骤操作&#xff0c;查看MuMu模拟器12本体以及多开模拟器的adb端口&#xff1a; 单开的MUMU模拟器12可通过模拟器右上角菜单-问题诊断&#xff0c;获取ADB调试端…