前言:最近接到一個任務,就是自定義一個Drawable以實現progressbar的加載效果,如圖: ![]java
要完成這個任務難點有二。 第一點:經過canvas和path繪製連續的顏色不一樣的平行四邊形 第二點:讓這一系列的平行四邊形動起來(利用valueanimator,在添加它的狀態改變的監聽,並調用invalidateSelf();刷新Drawable的draw方法) 下面直接上代碼,應該能夠看得懂:canvas
public class ColorfulProgressLoadingDrawable extends Drawable { private double unitHeight; private double unitSize; private int colorA; private int colorB; private int windowSize = 0; private float offset = 0; public ValueAnimator mValueAnimator; Path path = new Path(); ``` //colorA、B爲兩種傳入的顏色 public ColorfulProgressLoadingDrawable(int windowSize, double unitHeight, int colorA, int colorB) { this.windowSize = windowSize; this.unitHeight = unitHeight; this.colorA = colorA; this.colorB = colorB; this.unitSize = Math.sqrt(unitHeight * unitHeight / 3); } [@Override](https://my.oschina.net/u/1162528) public void draw([@NonNull](https://my.oschina.net/u/2981441) Canvas canvas) { ``` //此方法設置path,path爲平行四邊形 Paint paint = new Paint(); for (int i = 0; i < getShapeNumber(); i++) { if ((i + 1) % 2 == 1) { paint.setColor(colorA); } else { paint.setColor(colorB); } path.reset(); path.moveTo((float) (offset + windowSize - unitSize * i), 0); path.lineTo((float) (offset + windowSize - unitSize - unitSize * i), 0); path.lineTo((float) (offset + windowSize - 2 * unitSize - unitSize * i), (float) unitHeight); path.lineTo((float) (offset + windowSize - unitSize - unitSize * i), (float) unitHeight); canvas.drawPath(path, paint); } ``` } [@Override](https://my.oschina.net/u/1162528) public void setAlpha(int alpha) { } [@Override](https://my.oschina.net/u/1162528) public void setColorFilter([@Nullable](https://my.oschina.net/u/2896689) ColorFilter colorFilter) { } @Override public int getOpacity() { return PixelFormat.OPAQUE; } //計算要繪製的平行四邊形的個數 private int getShapeNumber() { return (int) (2 * (windowSize / unitSize)); } public void startAnimator() {; initValueAnimator(); mValueAnimator.start(); } private void initValueAnimator(){ if (mValueAnimator==null) { mValueAnimator = ValueAnimator.ofFloat(0, 4 * (float) unitSize); mValueAnimator.setInterpolator(new LinearInterpolator()); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { LogUtils.e("" + animation.getAnimatedValue()); offset = (float) animation.getAnimatedValue(); invalidateSelf(); } }); mValueAnimator.setDuration(1000); mValueAnimator.setRepeatCount(ValueAnimator.INFINITE); mValueAnimator.setRepeatMode(ValueAnimator.RESTART); } } public void stopAnimator() { if (mValueAnimator == null) { return; } else { mValueAnimator.cancel(); } } }
注意:在對Drawable進行引用的時候需調用startAnimator()開始動畫,以及在適當的時候調用stopAnimator來結束動畫以防止內存泄露。ide