一直就很想实现一个动画的自定义view研究一阵子之后终于有个小结果了。先上一个图助助兴,然后我们再慢慢道来。
gif1
实现起来也比较简单主要通过PathMeasure来测量出每一段路径然后再逐步获取出来通过canvas的draw方法绘制。具体代码如下
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Mr.Xu on 2017/1/8 0008.
*/
public class MyPathView extends View {
private static final String TAG = MyPathView.class.getSimpleName();
//画笔
private Paint mPaint;
//全部路径
private Path mPath;
//测量工具
private PathMeasure mPathMeasure;
//实时路径
private Path mDst;
//进度
private float mAnimatorValue;
//动画
ValueAnimator valueAnimator;
public MyPathView(Context context) {
this(context, null);
}
public MyPathView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPath = new Path();
//设置第一段横线路径
mPath.moveTo(0, 150);
mPath.lineTo(150, 150);
//画圆
mPath.addArc(new RectF(75, 0, 225, 150), 90, -359);
mPath.moveTo(150, 150);
//设置第二段路径
mPath.lineTo(300, 150);
//初始化测量工具传入完整路径
mPathMeasure = new PathMeasure(mPath, false);
//查看每段路径的长度
while (mPathMeasure.nextContour()) {
Log.e(TAG, "length=" + mPathMeasure.getLength());
}
//实例化实时路径
mDst = new Path();
mDst.reset();
mDst.lineTo(0, 0);
//因为上面调用了mPathMeasure.nextContour(),所以需要重置
mPathMeasure = new PathMeasure(mPath, false);
//实例化动画
valueAnimator = ValueAnimator.ofFloat(0, 1);
//平滑过渡
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
/**
*
* @param valueAnimator 0~1
*/
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mAnimatorValue = (float) valueAnimator.getAnimatedValue();
//实时路径的百分百比长度0->mPathMeasure.getLength()
float currentLength = mPathMeasure.getLength() * mAnimatorValue;
//将对应长度currentLength的路径获取并传递给mDst
mPathMeasure.getSegment(0, currentLength, mDst, true);
//重绘
invalidate();
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationRepeat(Animator animation) {
mPathMeasure.getSegment(0, mPathMeasure.getLength(), mDst, true);
//获取下一段路径
mPathMeasure.nextContour();
if (mPathMeasure.getLength() == 0) {
//如果全部绘制完成则重置
mDst.reset();
mDst.lineTo(0, 0);
mPathMeasure.setPath(mPath, false);
}
}
});
valueAnimator.setDuration(1000);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.RED);
canvas.drawPath(mDst, mPaint);
}
}
代码比较简单注释也很详细我就不重复说明了~,学会了之后可以自己实现一些简单的加载动画呢,效果不错。