Lottie - 让复杂动画如此简单

Introduction.gif
animation.gif

使用准备

Lottie支持多平台,使用同一个JSON动画文件,可在不同平台实现相同的效果。Android 通过Airbnb的开源项目lottie-android实现,最低支持 API 16;

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

dependencies {
  implementation 'com.airbnb.android:lottie:$lottieVersion'
}

最新的版本号可以到官网或者github查询,lottie仅支持api16及以上。

加载方式

1. src/main/assets

        lottieAnimationView = findViewById(R.id.lottieAnimationView);
        lottieAnimationView.setImageAssetsFolder("images");
        lottieAnimationView.setAnimation("data.json");
        lottieAnimationView.loop(true);
        lottieAnimationView.playAnimation();
<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_autoPlay="true" />

2. Json String

加载服务器上的.json文件,若有图片可以设置本地代理文件夹或者将图片资源放入 JSON。

private void loadUrl(String url) {
        Request request = new Request.Builder().url(url).build();
        OkHttpClient client = new OkHttpClient();
        client.newCall(request).enqueue(new Callback() {
            @Override public void onFailure(Call call, IOException e) {}
            @Override public void onResponse(Call call, Response response) throws IOException {
                try {
                    JSONObject json = new JSONObject(response.body().string());
                    LottieComposition.Factory
                            .fromJson(getResources(), json, new OnCompositionLoadedListener() {
                                @Override
                                public void onCompositionLoaded(LottieComposition composition) {
                                    lottieAnimationView.setComposition(composition);
                                    lottieAnimationView.playAnimation();
                                }
                            });
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    }

3. Url 服务器上的压缩包(包含images和json文件)

  • 通过url直接加载
 lottieAnimationView.setAnimationFromUrl(url);
 lottieAnimationView.playAnimation();
  • 下载到本地解压后指定文件夹代理
    // 资源zip
    public final static File LOTTIE_FILES = new File(Environment.getExternalStorageDirectory()+"/ctclient/lottie/lottie.zip");
    // 动效图片资源
    public final static File IMAGES_FILES = new File(Environment.getExternalStorageDirectory()+"/ctclient/lottie/images");
    // data.json路径
    public final static File JSON_FILE = new File(Environment.getExternalStorageDirectory()+"/ctclient/lottie/data.json");
    
    FileInputStream fis = null;
    if (JSON_FILE.exists()) {
        try {
            fis = new FileInputStream(JSON_FILE);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    if (fis == null || !IMAGES_FILES.exists()) {
        Log.i("huangssh", "动画资源不存在");
        return;
    }
    final String absolutePath = IMAGES_FILES.getAbsolutePath();
    // 开启硬件加速
    lottieAnimationView.useHardwareAcceleration(true);
    // 设置动画文件夹代理类
    lottieAnimationView.setImageAssetDelegate(new ImageAssetDelegate() {
        @Override
        public Bitmap fetchBitmap(LottieImageAsset asset) {
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inScaled = true;
            opts.inDensity = UtilPhoneParam.densityDpi;
            Bitmap bitmap = null;
            try {
                bitmap = BitmapFactory.decodeFile(absolutePath + File.separator + asset.getFileName(), opts);
            }catch (Exception e){
                e.printStackTrace();
            }
            return bitmap;
        }
    });
    
    // 设置动画
    LottieComposition.Factory.fromInputStream(fis, new OnCompositionLoadedListener() {
        @Override
        public void onCompositionLoaded(@Nullable LottieComposition composition) {
            lottieAnimationView.setComposition(composition);
            lottieAnimationView.playAnimation();
        }
    });

4. 加载SDCard字体

lottieAnimationView.setFontAssetDelegate(new FontAssetDelegate(){
    public Typeface fetchFont(String fontFamily) {
        Typeface customFont = Typeface.createFromFile(FONT_PATH + fontFamily);
        return customFont;
    }
});

常用方法

1. 监听动画进度 [0,1]

    lottieAnimationView.addAnimatorUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            // 判断动画加载结束
            if (valueAnimator.getAnimatedFraction() == 1f) {
                if (dialog.isShowing() && getActivity() != null)
                    dialog.dismiss();
            }
        }
    });

2. 暂停/取消/播放

lottieAnimationView.pauseAnimation();
lottieAnimationView.cancelAnimation();
lottieAnimationView.playAnimation();

3. 循环/播放某个部分

lottieAnimationView.loop(true);
  • ValueAnimator一样使用setRepeatMode(...)setRepeatCount(...)
  • scaleType :只支持centerCropcenterInside
  • 播放动画的某个部分
setMinFrame(...)
setMaxFrame(...)
setMinProgress(...)
setMaxProgress(...)
setMinAndMaxFrame(...)
setMinAndMaxProgress(...)

4. 硬件加速,解决lottie卡顿问题

lottieAnimationView.useHardwareAcceleration(true);

5. 缓存

/*
* Lottie内部有两个缓存map(强引用缓存,弱引用缓存),在动画文件加载完成后会根据设置的缓存策略缓存动画,方便下次使用。
*/
lottieAnimationView.setAnimation(animation, LottieAnimationView.CacheStrategy.Strong);    //强缓存

lottieAnimationView.setAnimation(animation, LottieAnimationView.CacheStrategy.Weak);      //弱缓存

根据进度缓存,并为下次播放作准备

lottieAnimationView.setProgress(progress);        //设置当前进度
lottieAnimationView.buildDrawingCache();          //强制缓存绘制数据
Bitmap image = lottieAnimationView.getDrawingCache(); //获取当前绘制数据

After Effects方面注意点(for设计师)

1. 官网动画实例 www.lottiefiles.com
2. AE文件预览 https://www.lottiefiles.com/preview
3. 在为Lottie构建时,您始终必须记住,这些JSON文件需要尽可能小巧令移动产品尽可能小。 例如,尽可能使用parenting。 在类似的图层上复制相同的关键帧会增加额外的代码。 只有在必要时才使用路径关键帧动画。 由于它为每个关键帧上的每个顶点添加数据,因此占用的空间最多。 诸如Autotrace之类的技术,或者每帧都为您提供关键帧的摇摆器,可能会使您的JSON文件非常大,并可能会对性能产生负面影响。 必须与组合物的设置方式保持平衡,以使事物尽可能高效。
4. 将任何Adobe Illustrator,EPS,SVG或PDF资源转换为After Effects中的图层,否则它们将无法在您的Lottie动画中使用。
5. Lottie尚不支持效果菜单中的表达式或任何效果。
6. 使用alpha遮罩会影响性能。 如果你使用的是alpha遮罩或alpha倒置遮罩,遮罩的大小会对性能产生更大的影响。 如果必须使用遮罩,请覆盖最小的区域。
7. 混合模式(如Multiply, Screen 或 Add)尚不受支持,也不支持Luma遮罩。
8. Lottie还不支持阴影,颜色叠加或笔触等图层效果。
9. 导出比您想要支持的最宽屏幕更宽的动画,使开发者在Android上使用centerCrop类型或在iOS上使用aspectFill内容模式。
10. 将图片资源放入JSON, 将图片资源整合到动画的 JSON文件中,开发人员的工作量就可以节约很多。
  • 需要先将图片转换成矢量图 SVG 格式,这个设计师一定有办法。
  • 使用 Illustrator 将 SVG 文件另存为 .ai 文件。
  • 使用 .ai 文件在 AE 中做动画处理。
  • 最后通过 Bodymovin 插件,输出动画资源。
    官方文档: artwork-to-lottie-walkthrough

引用文献

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容