Lottie - 动画的使用

作者: 因为我的心 | 来源:发表于2020-08-28 17:18 被阅读0次

    一、前言:

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

    现在使用各平台的 native 代码实现一套复杂的动画是一件很困难并且耗时的事,我们需要为不同尺寸的屏幕加载不同的素材资源,还需要写大量难维护的代码,而Lottie可以做到同一个动画文件在不同平台上实现相同的效果,极大减少开发时间,实现不同的动画,只需要设置不同的动画文件即可,极大减少开发和维护成本。

    Lottie 地址:https://github.com/airbnb/lottie-android

    Lottie 官网:https://airbnb.design/lottie/

    1、为什么使用Lottie?

    1. 跨平台只有制作一套json动画文件便可以跨平台在 Android ios ReactNeative上使用,lottie库负责解析json文件并播放动画

    2. 可以支持网络下载json文件,本地播放,实时更新动画资源。

    3. 运行时效率上仅仅用Canvas去draw而已,流畅度非常棒,所以哪怕在Listview里去大量显示,内存占用和绘图效率都远远高于帧动画。

    4. 实现效果可以按设计出的100%还原到产品中。

    5. 开发周期大大减少。

    二、使用:

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

    dependencies {
         //lottie框架(现在的最新版本)
        implementation'com.airbnb.android:lottie:3.4.1'
    }
    
    

    注意:版本过老,会报错

    2、 添加 Adobe After Effects 导出的动画文件

    Lottie默认读取Assets中的文件,我们需要把设计导出的动画文件.json 保存在app/src/main/assets文件里。

    位置.png

    比如p_start.json中包含本地图片,则在assets中新建images文件夹,将图片放入即可


    图片.png

    3、 使用Lottie

    1. 直接布局加载*.json文件的方法:
      <com.airbnb.lottie.LottieAnimationView
                android:id="@+id/animation_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                app:lottie_fileName="app_loading.json"
                app:lottie_loop="true" />
    
    

    lottie_fileName表示本地Assets文件中存的json动画文件

    lottie_loop表示动画循环执行

    2、代码加载动画方法

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

    lottie_autoPlay表示设置是否自动启动播放

            //声明控件
            lottieAnimationView = findViewById(R.id.animation_view);
            //这个可有可无,如果不涉及本地图片做动画可忽略
           // lottieAnimationView.setImageAssetsFolder("images");
            //设置动画文件
            lottieAnimationView.setAnimation("app_loading.json");
            //是否循环执行
            lottieAnimationView.loop(true);
            //执行动画
            lottieAnimationView.playAnimation();
    
    
    1. 加载网络.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();
                    }
                }
            });
        }
    
    
    1. 使用包含本地图片的lottie动画
      XML使用:
       <com.airbnb.lottie.LottieAnimationView
                    android:id="@+id/lottie_view"
                    android:layout_width="@dimen/dp_70"
                    android:layout_height="@dimen/dp_50"
                    app:lottie_fileName="p_start.json"
                    app:lottie_imageAssetsFolder="images/"
                    android:layout_below="@+id/tv_level1"
                    android:layout_centerHorizontal="true"
                    android:layout_marginTop="@dimen/dp_6"
                    />
    

    java代码:

       //动画1
        private fun initAnible() {
            //这个可有可无,如果不涉及本地图片做动画可忽略
            lottie_view.setImageAssetsFolder("images/");
            //设置动画文件
            lottie_view.setAnimation("p_start.json");
            //是否循环执行
            //lottie_view.loop(true);
            lottie_view.setOnClickListener {
                //执行动画
                lottie_view.playAnimation()
            }
        }
    

    三、 常用方法

    • animationView.isAnimating();  动画是否在播放
    • animationView.playAnimation();    播放动画
    • animationView.pauseAnimation();   暂停动画
    • animationView.cancelAnimation();  取消动画
    • animationView.setProgress(progress);  设置进度,progress范围0~1
    • animationView.setMinAndMaxProgress(min,max);  设置播放范围,0~1
    • 监听动画进度
    • 设置动画硬件加速
    • 缓存动画
    • Lottie本身在 Android 平台已经做了适配工作,而且适配原理很简单,解析时,从 读取宽高之后会再乘以手机的密度。再在使用的时候判断适配后的宽高是否超过屏幕的宽高,如果超过则再进行缩放。以此保障 Lottie 在 Android 平台的显示效果

    四、自定义刷新头

    public class CustomClassicsHeader extends LinearLayout implements RefreshHeader {
    
        private TextView mHeaderText;//标题文本
    //    private ImageView mArrowView;//下拉箭头
    //    private ImageView mProgressView;//刷新动画视图
    //    private ProgressDrawable mProgressDrawable;//刷新动画
        private LottieAnimationView lottieAnimationView;//加载动画
        private   View view;
        public CustomClassicsHeader(Context context) {
            this(context, null);
        }
    
        public CustomClassicsHeader(Context context, AttributeSet attrs) {
            super(context, attrs, 0);
    
             view = LayoutInflater.from(context).inflate(R.layout.item_custom_header, this);
    //        setGravity(Gravity.CENTER);
    //        mHeaderText = new TextView(context);
    //        mProgressDrawable = new ProgressDrawable();
    ////        mArrowView = new ImageView(context);
    ////        mProgressView = new ImageView(context);
    //        lottieAnimationView = new LottieAnimationView(context);
    //        //mProgressView.setImageDrawable(mProgressDrawable);
    //        //mArrowView.setImageDrawable(new ArrowDrawable());
    //
    //        mHeaderText.setTextColor(context.getResources().getColor(R.color.color_FF333333));
    ////        addView(mProgressView, SmartUtil.dp2px(20), SmartUtil.dp2px(20));
    ////        addView(mArrowView, SmartUtil.dp2px(20), SmartUtil.dp2px(20));
    //        addView(lottieAnimationView, SmartUtil.dp2px(25), SmartUtil.dp2px(25));
    //        addView(new Space(context), SmartUtil.dp2px(20), SmartUtil.dp2px(20));
    //        addView(mHeaderText, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    //        setMinimumHeight(SmartUtil.dp2px(60));
    //        //加载动画
    //        lottieAnimationView.setAnimation("app_pull_refresh.json");
    //        //是否循环执行
    //        lottieAnimationView.loop(true);
    
    
            lottieAnimationView = view.findViewById(R.id.lottieAnimationView);
            mHeaderText = view.findViewById(R.id.tv_head);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
        }
    
        @NonNull
        public View getView() {
            return view;//真实的视图就是自己,不能返回null
        }
    
        @NonNull
        @Override
        public SpinnerStyle getSpinnerStyle() {
            return SpinnerStyle.Translate;//指定为平移,不能null
        }
    
        @Override
        public void onStartAnimator(@NonNull RefreshLayout layout, int height, int maxDragHeight) {
           // mProgressDrawable.start();//开始动画
            //执行动画
            lottieAnimationView.playAnimation();
        }
    
        @Override
        public int onFinish(@NonNull RefreshLayout layout, boolean success) {
    //        mProgressDrawable.stop();//停止动画
    //        mProgressView.setVisibility(GONE);//隐藏动画
            lottieAnimationView.cancelAnimation();
            if (success) {
                mHeaderText.setText("刷新完成");
            } else {
                mHeaderText.setText("刷新失败");
            }
            return 500;//延迟500毫秒之后再弹回
        }
    
        @Override
        public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) {
            refreshLayout.setPrimaryColorsId(R.color.color_FFF96857,R.color.color_FFF96857);//全局设置主题颜色
            switch (newState) {
                case None:
                case PullDownToRefresh:
                    mHeaderText.setText("下拉开始刷新");
    //                mArrowView.setVisibility(VISIBLE);//显示下拉箭头
    //                mProgressView.setVisibility(GONE);//隐藏动画
    //                mArrowView.animate().rotation(0);//还原箭头方向
    
                    break;
                case Refreshing:
                    mHeaderText.setText("正在刷新");
    //                mProgressView.setVisibility(VISIBLE);//显示加载动画
    //                mArrowView.setVisibility(GONE);//隐藏箭头
                    break;
                case ReleaseToRefresh:
                    mHeaderText.setText("释放立即刷新");
                   // mArrowView.animate().rotation(180);//显示箭头改为朝上
                    break;
            }
        }
    
        @Override
        public void setPrimaryColors(int... colors) {
    
        }
    
        @Override
        public void onInitialized(@NonNull RefreshKernel kernel, int height, int maxDragHeight) {
    
        }
    
        /**
         * 移动
         * @param isDragging
         * @param percent
         * @param offset
         * @param height
         * @param maxDragHeight
         */
        @Override
        public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {
            if(isDragging){
                //设置进度
                lottieAnimationView.setProgress(percent);
            }
    
        }
    
        @Override
        public void onReleased(@NonNull RefreshLayout refreshLayout, int height, int maxDragHeight) {
    
        }
    
        @Override
        public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) {
    
        }
    
        @Override
        public boolean isSupportHorizontalDrag() {
            return false;
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_70"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:background="@color/color_FFFFFF"
        >
        <com.airbnb.lottie.LottieAnimationView
            android:id="@+id/lottieAnimationView"
            android:layout_width="@dimen/dp_35"
            android:layout_height="@dimen/dp_35"
            android:layout_marginTop="@dimen/dp_10"
            app:lottie_fileName="app_pull_refresh.json"
            app:lottie_loop="true"
            app:lottie_autoPlay="true"
            android:layout_centerHorizontal="true"
            />
    
        <TextView
            android:id="@+id/tv_head"
            android:layout_marginTop="@dimen/dp_3"
            android:layout_below="@+id/lottieAnimationView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/color_FFA9A9A9"
            android:textSize="@dimen/sp_11"
            android:layout_centerHorizontal="true"
            android:text="下拉开始刷新"
            />
    </RelativeLayout>
    

    相关文章

      网友评论

        本文标题:Lottie - 动画的使用

        本文链接:https://www.haomeiwen.com/subject/psglsktx.html