Lottie for Android:Json 动画框架 Lottie 的使用及加载 zip 压缩文件的方法

无人久伴 提交于 2019-12-25 10:19:50

Json 动画加载框架 Lottie,在网上已经有很多的相关文章了,但是版本都比较老,单独加载 json 文件的还可以,涉及到加载 zip 压缩文件的几乎没有,所以下面就稍稍列出常用的 json 动画加载方式,再稍稍重点说一下加载 zip 压缩文件的方法。

lottie-android github 地址

lottie 官网

本文 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();
    }
});

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!