优雅地使用Drawable做动画
2018-11-28 本文已影响0人
我是二哥呀
效果
[图片上传失败...(image-43a1a3-1543390766656)]
下载
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
戴书文 - 153513741@qq.com