先上效果圖
實現原理
其實這種不規則的動畫,以及支付寶的支付成功動畫,實現原理都差不多,首先就是利用Path畫出完成的圖案路徑,然後利用PathMeasure測量出路徑的長度,然後PathMeasure截取出Path的片段,再結合屬性動畫,截取出時間上連續的Path路徑,然後繪製出path就完成了,代碼很簡單,主要是這種思想,可以實現各種各樣的炫酷的小動畫。
代碼實現
public class MyProgress extends View {
private Context mContext;
private Paint mPaint;
private Path mPath;
private PathMeasure mPathMeasure;
private float mLength;
private float mAnimatorValue;
private Path dst;
public MyProgress(Context context) {
this(context, null);
}
public MyProgress(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
private void init() {
//畫筆
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.parseColor("#FF4081"));
mPaint.setStrokeWidth(10f);
mPaint.setStyle(Paint.Style.STROKE);
//Path
dst = new Path();
mPath = new Path();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPath.addCircle(getWidth()/2, getWidth()/2, getWidth()/4, Path.Direction.CW);//加入一個半徑爲100圓
mPathMeasure = new PathMeasure(mPath, true);
mLength = mPathMeasure.getLength();
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addUpdateListener(animation -> {
mAnimatorValue = (float) animation.getAnimatedValue();
invalidate();
});
animator.setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);//無限循環
animator.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
dst.reset();
float distance = mLength * mAnimatorValue;
// distance start disant -0
float start = (float) (distance - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength));
// ( distance-0.5*mLength) start distance
//mPath 1 dst 2
mPathMeasure.getSegment(start, distance, dst, true);
canvas.drawPath(dst, mPaint);
}
}
使用就很簡單了
public class ProgressActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyProgress(this));
}
}