美文网首页
LottieAnimationView场景恢复-导致的底部按钮显

LottieAnimationView场景恢复-导致的底部按钮显

作者: HuBoZzz | 来源:发表于2019-03-19 10:59 被阅读0次

    记录一个遇到的问题

    使用Lottie优雅的实现矢量动画,用起来妙啊,能够做到普通帧动画无法做到的功能,模仿的腾讯视频底部切换的动画.但是使用中发现了下图的问题.

    Animation.gif

    我在这里点了快速运行,导致本身四个不同的图片变成和最后一个图片一样的了.,其实旋转屏也可以复现!
    然鹅,如果出现这个问题的时候是旋转屏,我会直接晓得是场景恢复导致的,但是我发现的时候是快速运行和崩溃的时候复现的,我没有联想到,所以我找了好久.

    那么问题已经找到了就是场景恢复导致的,那就去定位问题吧.

    lottie 源码版本

    implementation 'com.airbnb.android:lottie:2.7.0'
    

    既然大致知道是场景恢复引发的这个事件,那么就直接查LottieAnimationView的这两个方法

    • onSaveInstanceState
    • onRestoreInstanceState

    看了一下LottieAnimationView果然重写了这两个方法
    onSaveInstanceState,果然保存了动画的属性,o(╥﹏╥)o

      @Override protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.animationName = animationName;
        ss.animationResId = animationResId;
        ss.progress = lottieDrawable.getProgress();
        ss.isAnimating = lottieDrawable.isAnimating();
        ss.imageAssetsFolder = lottieDrawable.getImageAssetsFolder();
        ss.repeatMode = lottieDrawable.getRepeatMode();
        ss.repeatCount = lottieDrawable.getRepeatCount();
        return ss;
      }
    

    onRestoreInstanceState 恢复的时候把对应的动画属性恢复过来了

    @Override protected void onRestoreInstanceState(Parcelable state) {
        if (!(state instanceof SavedState)) {
          super.onRestoreInstanceState(state);
          return;
        }
    
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        animationName = ss.animationName;
        if (!TextUtils.isEmpty(animationName)) {
          setAnimation(animationName);
        }
        animationResId = ss.animationResId;
        if (animationResId != 0) {
          setAnimation(animationResId);
        }
        setProgress(ss.progress);
        if (ss.isAnimating) {
          playAnimation();
        }
        lottieDrawable.setImagesAssetsFolder(ss.imageAssetsFolder);
        setRepeatMode(ss.repeatMode);
        setRepeatCount(ss.repeatCount);
      }
    

    你会说没毛病呀,一个对象一个资源,不会导致4个对象使用一个资源呀!这里先把原因说出来.
    这四个LottieAnimationView有相同的id.
    给你看个布局 R.layout.view_maintab,

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/white">
    
        <com.airbnb.lottie.LottieAnimationView
            android:id="@+id/view_maintab_img"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="5dp" />
    
    //...省略
    
    
    public class MainTab extends FrameLayout {
        public MainTab(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
           LayoutInflater.from(context).inflate(R.layout.view_maintab,
                    this);
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MainTab);
            String titleContent = typedArray.getString(R.styleable.MainTab_text);
            Drawable drawable = typedArray.getDrawable(R.styleable.MainTab_img_res);
            typedArray.recycle();
    

    自定义了一个FrameLayout用来装布局,然后写一些共同的属性,来实现切换的tab!
    问题原因:
    这里因为场景恢复的数据通过onSaveInstanceState()先存到一个SparseArray<Parcelable> container集合里,通过dispatchRestoreInstanceState()通过id来取出对应的数据.

       protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
            if (mID != NO_ID) {
                //注意看这里
                Parcelable state = container.get(mID);
                if (state != null) {
                    mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
                    onRestoreInstanceState(state);
                 //....
                }
            }
        }
    

    在执行onSaveInstanceState()的时候最后一个tab因为id和前面的三个一致,直接覆盖了前面的数据.这就是问题的原因,那怎么办呢?

    解决方式:
    不写id了就好了呗!那你怎么获取对象呢?可以使用getChild()....等方式拿到对象.

    此处应有签名

    相关文章

      网友评论

          本文标题:LottieAnimationView场景恢复-导致的底部按钮显

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