自定义View实战 | 弹跳的loading效果

作者: 凌川江雪 | 来源:发表于2019-09-14 12:37 被阅读0次
    • app加载中状态,有图片上下跳动,并每跳一次换一张图片

    • 首先准备几张图片

    思路
    • 这个控件应该派生自ImageView类,这样才能方便地更改它的源文件内容;

    • 实现上下移动的效果:
      利用ValueAnimator实时产生一个0~100的数值,
      让当前图片的位置实时向上移动ValueAnimator的动态值的高度即可。

    • 要让图片的位置实时向上移动,
      就需要先拿到初始状态下图片的位置。
      每次控件被布局时
      都会调用
      onLayout(boolean changed,int left,int top,int right,int bottom)函数,
      其中的参数left、top、right、bottom就是当前控件的位置。

      通过重写onLayout()函数,我们可以拿到控件的初始高度mTop
      之后在每次ValueAnimator的动态值到来时,
      计算出当前控件的top位置,并将控件移动到这个位置就可以了。

    实现
    • 自定义一个控件LoadingImageView,派生自ImageView,
      重写onLayout()函数,拿到控件的初始top值
      onLayout()函数只在一开始创建Activity的时候调用了一次而已,
      后面我们是通过ValueAnimator来改变高度值,
      没有调用到onLayout()函数)

    • init() 函数中,创建并初始化ValueAnimator实例:
      通过(mTop-dx)得到当前控件相对初始坐标上移dx距离后的最新坐标点;
      通过setTop(int top)函数将控件移动到当前位置。

    • getTop()和setTop(int top)函数所得到的和设置的坐标
      都是相对父控件的坐标位置。

    • 监听动画的开始和重复。
      当动画开始时,图片设置为imagetest1.jpg;
      在重复时,每重复一次更换一张图片。

    public class LoadingImageView extends ImageView {
    
        private int mTop;
    
        //当前动画图片索引
        private int mCurImgIndex = 0;
    
        //动画图片总张数
        private static int mImgCount = 3;
    
        public LoadingImageView(Context context) {
            super(context);
            init();
        }
    
        public LoadingImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public LoadingImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
    
            mTop = top;
        }
    
        private void init() {
            ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100, 0);
            valueAnimator.setRepeatCount(valueAnimator.RESTART);
            valueAnimator.setRepeatCount(valueAnimator.INFINITE);
            valueAnimator.setDuration(2000);
            valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Integer dx = (Integer) animation.getAnimatedValue();
                    setTop(mTop - dx);
                }
            });
    
            valueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    setImageDrawable(getResources(). getDrawable(R.drawable.imagetest1));
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
    
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
                    mCurImgIndex++;
                    switch (mCurImgIndex % mImgCount) {
                        case 0:
                            setImageDrawable(getResources(). getDrawable(R.drawable.imagetest1));
                            break;
    
                        case 1:
                            setImageDrawable(getResources(). getDrawable(R.drawable.imagetest2));
                            break;
    
                        case 2:
                            setImageDrawable(getResources(). getDrawable(R.drawable.imagetest3));
                            break;
                    }
                }
            });
    
            valueAnimator.start();
        }
    }
    
    • 使用控件并运行
    case 5:
                    LoadingImageView loadingImageView = new LoadingImageView(this);
    
                    ll_nextParent.addView(loadingImageView, layoutParams);
                    break;
    
    • 完整项目代码敬请见GitHub

    相关文章

      网友评论

        本文标题:自定义View实战 | 弹跳的loading效果

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