最近專案要求做一個進度條,頭部有一個龜頭小圓,如下:

拿到圖第一時間就是對整個圖片進行技術拆分,由內到外可分為5個部分:

1.繪制實心圓
Paint pain=new Paint;
pain.setStyle(Paint.Style.FILL);
addCircle(float x, float y, float radius, @NonNull Direction dir)
2.繪制二階貝塞爾曲線
quadTo(float x1, float y1, float x2, float y2)
3.根據4的軌跡通過PathMeasure 截取 片段
getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)
4.繪制空心圓
Paint pain=new Paint;
pain.setStyle(Paint.Style.STROKE);
addCircle(float x, float y, float radius, @NonNull Direction dir)
5.一個外圈空心圓包裹一個內圈實心圓
pathMeasure.getPosTan
1和2部分下一篇博客加上,因為涉及貝塞爾曲線
好了, 來看看3-5核心代碼,
private void initView(Context context, AttributeSet attrs) {
//內圈畫筆
insidePaint = new Paint();
insidePaint.setAntiAlias(true);//去鋸齒
insidePaint.setStyle(Paint.Style.STROKE);
insidePaint.setStrokeWidth(insideStrokeWidth);
insidePaint.setColor(Color.WHITE);
//外圈畫筆
outsidePaint = new Paint();
outsidePaint.setAntiAlias(true);//去鋸齒
outsidePaint.setStyle(Paint.Style.STROKE);
outsidePaint.setStrokeWidth(outSideStrokeWidth);
outsidePaint.setColor(Color.WHITE);
//小龜頭空心圓圈畫筆
smallPaint = new Paint();
smallPaint.setAntiAlias(true);
smallPaint.setStyle(Paint.Style.STROKE);
smallPaint.setStrokeWidth(smallStrokeWidth);
smallPaint.setColor(Color.WHITE);
//小龜頭內圈物體圓圈畫筆
smallInsidePaint = new Paint();
smallInsidePaint.setAntiAlias(false);
smallInsidePaint.setStyle(Paint.Style.FILL);
smallInsidePaint.setColor(getResources().getColor(R.color.color_5FBBEB));
}
大致是初始化了4個畫筆,從上到下分別負責:4-3-5
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
outSidePath = new Path();
insidePath = new Path();
insidePath.addCircle((w) / 2f + insideStrokeWidth
, (h) / 2f + insideStrokeWidth
, (h) / 2f - 2 * insideStrokeWidth - outSideStrokeWidth
, Path.Direction.CW);
pathMeasure.setPath(insidePath, true);
}
在 sizeChanged階段 初始化 外圈 內圈 的路徑Path,并且初始化內圈半徑引數
核心部分
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
outSidePath.reset();
float length = pathMeasure.getLength();
canvas.drawPath(insidePath, insidePaint);
float startD = 0;
float stopD = (Math.abs(progress)) / 100f * length;
pathMeasure.getSegment(startD, stopD, outSidePath, true);
if (progress != 1) {
canvas.drawPath(outSidePath, outsidePaint);
}
pathMeasure.getPosTan(stopD + 2 + outSideStrokeWidth, pos, tan);
Log.d(TAG, "THE POS IS:" + pos[0] + "tan:" + tan[0] + "...stopD:" + stopD);
if (progress != 100 && progress != 1) {
//繪制龜頭外圈
canvas.drawCircle(pos[0], pos[1], outSideRadius, smallPaint);
//繪制龜頭外圈
canvas.drawCircle(pos[0], pos[1], (outSideRadius - smallStrokeWidth / 2), smallInsidePaint);
}
}
繪制階段大部分都是計算:有截取片段的開始startD 、stopD和 求曲線路徑當前正切坐標值getPosTan
通過外部傳進來的Progress 進度控制 截取長度,進而達到類似progress 一直在動的效果,
最后得到初步效果如下:
ps:下方黑色的動效為:Android 自定義View 之 Path PathMeasure (一)

剛開始寫博客,格式不是很好,湊合著看吧,有需要的可以私信 ~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/1304.html
標籤:其他
上一篇:Android的三大影片
