Json 动画加载框架 Lottie,在网上已经有很多的相关文章了,但是版本都比较老,单独加载 json 文件的还可以,涉及到加载 zip 压缩文件的几乎没有,所以下面就稍稍列出常用的 json 动画加载方式,再稍稍重点说一下加载 zip 压缩文件的方法。
本文 demo 时采用的是当时最新 lottie-android 版本:
dependencies {
implementation 'com.airbnb.android:lottie:3.3.1'
}
地址是上面的 lottie-android github 地址:
json 动画文件可以通过专业软件 AE 转换 gif 文件得来,当然求求 UI 大大也是可以有的。
1、在 xml 指定 json 动画文件
// 放在raw文件夹
<com.airbnb.lottie.LottieAnimationView
... ...
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/test" />
// 放在assets文件夹
<com.airbnb.lottie.LottieAnimationView
... ...
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_fileName="test.json" />
2、代码中动态设置 json 动画文件
// raw文件夹
mAnimationView.setAnimation(R.raw.test);
mAnimationView.setRepeatMode(LottieDrawable.REVERSE);//设置播放模式
mAnimationView.setRepeatCount(LottieDrawable.INFINITE);//设置重复次数
mAnimationView.playAnimation();
// assets文件夹
mAnimationView.setAnimation("test.json");
mAnimationView.setRepeatMode(LottieDrawable.REVERSE);//设置播放模式
mAnimationView.setRepeatCount(LottieDrawable.INFINITE);//设置重复次数
mAnimationView.playAnimation();
3、通过 string 加载 json 动画
// 如果string内容是错误格式的json,app会直接崩溃,里面是异步的,可以通过LottieAnimationView.setFailureListener监听失败
String jsonString = "{\"aaa\":[],\"bbb\":[]}";
mAnimationView.setAnimationFromJson(jsonString, null);
mAnimationView.setFailureListener(new LottieListener<Throwable>() {
@Override
public void onResult(Throwable result) {
result.printStackTrace();
}
});
mAnimationView.playAnimation();
4、加载网络 json 动画文件
// 如果url不存在,app会直接崩溃,里面是异步的,可以通过LottieAnimationView.setFailureListener监听失败
mAnimationView.setAnimationFromUrl("https://xxx.com/test.json");
mAnimationView.setFailureListener(new LottieListener<Throwable>() {
@Override
public void onResult(Throwable result) {
result.printStackTrace();
}
});
mAnimationView.playAnimation();
5、加载 assets 文件夹中 json 文件和 images 配合的动画
mAnimationView.setImageAssetsFolder("xxx/images");// 指定配合的images文件夹
mAnimationView.setAnimation("xxx/data.json");// json文件中要指定同级目录中images名及图片文件名
mAnimationView.playAnimation();
json 动画可以单独通过一个 json 文件加载动画,动画中可能有某部分是不变的,或者只做简单的动画效果(平移、缩放、旋转 等等等等),如果只通过一个 json 文件去描述,那么文件会很大,可能比要简化的 gif 文件还大,但是,把其中某些部分制作成图片, 通过 json 索引到指定的图片,这样做出来的文件数虽然多了,但是整体大小会小非常之多。
6、加载 assets 文件夹中的 zip 文件
流量在某些情况下会很费钱、费时,所以可以通过牺牲一点性能的方式换取流量的节省、时间的节省,这是很划算的,所以,可以把 json 动画相关文件做压缩下发,在拿到时解压缩后使用。本点是放在 apk 包中,代码中设置指定文件,Lottie 会帮我们解压,下面再说网络下发的用法。保持 apk 包的瘦小,也是对攻城狮的要求。
mAnimationView.setAnimation("test.zip");
mAnimationView.playAnimation();
7、在 xml 指定 zip 动画文件
// 可以直接索引到assets中的zip文件,但是不能索引raw中的zip文件,运行会报错
<com.airbnb.lottie.LottieAnimationView
... ...
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_fileName="test.zip" />
8、加载网络上的 zip 文件
Lottie 可以通过设置网络 json 文件和 zip 压缩文件 url 加载特定动画,上面有加载网络 json 文件的用法,只要设置 url ,Lottie 会帮我们做剩下的工作。
String zipUrl = "https://xxx.com/test.zip";
mAnimationView.setAnimationFromUrl(zipUrl);
mAnimationView.setFailureListener(new LottieListener<Throwable>() {
@Override
public void onResult(Throwable result) {
result.printStackTrace();
}
});
mAnimationView.playAnimation();
但是,上面代码中,在加载网路 zip 压缩文件时,总是报下面的错误:
谷歌度娘找了几圈,也没有相应的解决方法,只能自己看源码了,最后发现 Lottie 代码中在判断 zip 压缩文件的 mime 类型时,出现以下的不匹配:
通过 python 读取 zip 文件的 mime type:
所以,又谷歌度娘几圈关于 application/zip 和 application/x-zip-compressed 的区别和转换,应该是差不多的,可能是不同系统环境造成的差异,但是找得到 mime type 的读取方法,就是找不到 application/zip 和 application/x-zip-compressed 之间的转换方法,通过这种方法解决上面问题的路走不通了;那就偷懒一下,通过重写相关类解决问题,但是发现各种 private,这条路也走不通,难道要我把整个 module 代码拷出来“做大手术”;最后,通过乖乖读源码,还是找到了一小条“活路”,用下面的方式解决问题:
private void getZipFromUrl() {
String zipUrl = "https://xxx.com/test.zip";
if (!zipUrl.endsWith(".zip")) {
return;
}
Runnable runnable = new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
ZipInputStream zipInputStream = null;
try {
HttpURLConnection connection = (HttpURLConnection) new URL(zipUrl).openConnection();
connection.setRequestMethod("GET");
connection.connect();
if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return;
}
String contentType = connection.getContentType();
if (contentType.contains("application/x-zip-compressed")) {
inputStream = connection.getInputStream();
// 设置zip流
zipInputStream = new ZipInputStream(inputStream);
LottieTask<LottieComposition> task = LottieCompositionFactory.fromZipStream(zipInputStream, null);
task.addListener(new LottieListener<LottieComposition>() {
@Override
public void onResult(LottieComposition result) {
mAnimationView.setComposition(result);
mAnimationView.playAnimation();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
ThreadUtil.runInWorkThread(runnable);
}
关键代码是读文件流和下面的代码:
LottieTask<LottieComposition> task = LottieCompositionFactory.fromZipStream(zipInputStream, null);
task.addListener(new LottieListener<LottieComposition>() {
@Override
public void onResult(LottieComposition result) {
mAnimationView.setComposition(result);
mAnimationView.playAnimation();
}
});
当然,如果 zip 压缩文件的 mime type 本身就是 application/zip,或者有 application/zip 和 application/x-zip-compressed 的转换方法,还是采用 Lottie 提供的 api 更稳健些。
最后还要注意一点,Lottie 获取文件和设置绘制动画用到很多异步,说不定什么时候就崩一下,最好通过 LottieAnimationView.setFailureListener 去监听失败,做好后续处理:
mAnimationView.setFailureListener(new LottieListener<Throwable>() {
@Override
public void onResult(Throwable result) {
result.printStackTrace();
}
});
来源:CSDN
作者:zeqiao
链接:https://blog.csdn.net/zeqiao/article/details/103685236