优雅地使用Drawable做动画

效果

[图片上传失败...(image-43a1a3-1543390766656)]

下载

下载地址

github

github

实现上图动画,可以有以下几种方式

1.布局里写三个view, 然后用一个ValueAnimator改变这三个view的height

  • 太糙了,一个loading动画,你要放三个view进去,那要是100条线的动画呢=_=||

2.自定义一个view, 在这个view里面放一个ValueAnimator,在onDraw方法里面绘制三条线

  • 就一个loading动画,你要自定义一个view,是不是有点不够灵活,而且有点重了

3.Lottie、SVGA等第三方动画库

  • 当这个动画面积比较大的时候,或者这个动画要放在recyclerview的item里的时候,会有性能瓶颈

4.自定义Drawable

  • 本质有点类似阉割版的view,好处是可以直接放在ImageView里,或者作为任意一个view的background

这篇文章重点介绍自定义drawable

  • 核心是draw方法
@Override
    public void draw(@NonNull Canvas canvas) {
        for (int i = 0; i < 3; i++) {
            canvas.save();
            canvas.translate(mDeltaX * (1 + i), mDeltaY);
            canvas.drawLine(0, canvas.getHeight() * getFractionByIndex(i) / -4,
                    0, canvas.getHeight() / 4 * getFractionByIndex(i), mPaint);
            canvas.restore();
        }
    }
  • 在构造方法里创建一个ValueAnimation
public class CustomDrawable extends Drawable implements Animatable
public CustomDrawable() {
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(STROKE_WIDTH_PX);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mAnimator = ValueAnimator.ofFloat(0.4f, 1f).setDuration(300);
        mAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mAnimator.setRepeatMode(ValueAnimator.REVERSE);
        mAnimator.addUpdateListener(animation -> {
            mFraction = (float) animation.getAnimatedValue();
            invalidateSelf();
        });
    }
  • 需要重写下列方法
@Override
    public void start() {
        if (mAnimator == null) return;
        if (mAnimator.isRunning()) return;
        mAnimator.start();
    }

    @Override
    public void stop() {
        if (mAnimator == null) return;
        mAnimator.cancel();
    }


    @Override
    public boolean isRunning() {
        return mAnimator != null && mAnimator.isRunning();
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        mDeltaX = bounds.width() / 4;
        mDeltaY = bounds.height() / 2;
    }

tips

别忘了释放动画,以免造成内存泄漏

@Override
    protected void onResume() {
        super.onResume();
        mDrawable.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mDrawable.stop();
    }

Author

戴书文 - [email protected]

你可能感兴趣的:(优雅地使用Drawable做动画)