上週遇到一個需求,用一個圓形進度條的形式來展示某項操作所佔的比例,雖然類似的輪子已經有很多了,但是這種簡單的自定義View個人覺得有時間的話,還是自己寫寫比較好。
首先來看一下效果圖:
實現效果
分析: 從效果圖可以看到,這個效果整體分爲以下幾部分:
- 背景圓環
- 進度圓弧
- 終點小圓圈(進度爲0和進度爲100%的時候應當沒有)
- 內部三行文字
怎麼實現: 分析出整體框架之後,思路其實已經很簡單了,我是這樣實現的:
- 畫背景圓
- 按照當前進度計算出掃過的弧度來畫一個圓弧
- 以第二步的圓弧結束位置爲座標,畫兩個大小不同的實心圓,達到設計效果
- 分別畫三行文字
第三步中,在確定圓弧終點位置的時候用到了三角函數,這裏簡單畫了一個圖,很好理解:
三角函數計算圓弧終點位置座標
以頂點爲起點,圓半徑爲r,圓弧掃過的角度爲α。
代碼 簡單列下主要代碼,完整代碼地址放在了文字末尾。 1.爲了更加靈活,我這裏提供了很多屬性用於用戶自己來設置:
private String title; private String num; private String unit; private float titleTextsize; private float numTextsize; private float unitTextsize; private int titleTextColor; private int numTextColor; private int unitTextColor; private float backCircleWidth; private float outerCircleWidth; private int backCircleColor; private int outerCircleColor; private float endCircleWidth; private int endCircleColor;
2.爲了代碼更加清晰,設置瞭如下Paint
private Paint backCirclePaint,//畫背景圓 outerCirclePaint,//畫進度圓弧 endCirclePaint,//畫終點實心大圓 endCirclePaint2,//畫終點實心小圓 titlePaint,//畫第一行文字 numPaint,//畫第二行文字 unitPaint;//畫第三行文字
3.在onDraw方法中實現繪製操作
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = width / 2; int centerY = height / 2; //計算半徑 float radius = (width / 2) - outerCircleWidth + (outerCircleWidth - backCircleWidth) / 2; //畫背景圓 canvas.drawCircle(centerX, centerY, radius, backCirclePaint); //根據進度話掃過一定角度的圓弧 RectF rectF = new RectF(outerCircleWidth / 2 + backCircleWidth / 2, outerCircleWidth / 2 + backCircleWidth / 2, width - outerCircleWidth / 2 - backCircleWidth / 2, height - outerCircleWidth / 2 - backCircleWidth / 2); canvas.drawArc(rectF, -90, 360 * currentPercent, false, outerCirclePaint); //畫三行文字 Rect textRect = new Rect(); titlePaint.getTextBounds(title, 0, title.length(), textRect); canvas.drawText(title, width / 2 - textRect.width() / 2, height / 4 + textRect.height() / 2, titlePaint); numPaint.getTextBounds(num, 0, num.length(), textRect); canvas.drawText(num, width / 2 - textRect.width() / 2, height / 2 + textRect.height() / 2, numPaint); unitPaint.getTextBounds(unit, 0, unit.length(), textRect); canvas.drawText(unit, width / 2 - textRect.width() / 2, height * 2 / 3 + textRect.height() / 2, unitPaint); //我這裏規定進度在0~100%的時候纔會畫終點小圓,可以自由改動 if (currentPercent < 1 && currentPercent > 0) { canvas.drawCircle(centerX + rectF.width() / 2 * (float) Math.sin(360 * currentPercent * Math.PI / 180), centerY - rectF.width() / 2 * (float) Math.cos(360 * currentPercent * Math.PI / 180), endCircleWidth / 2, endCirclePaint); canvas.drawCircle(centerX + rectF.width() / 2 * (float) Math.sin(360 * currentPercent * Math.PI / 180), centerY - rectF.width() / 2 * (float) Math.cos(360 * currentPercent * Math.PI / 180), endCircleWidth / 4, endCirclePaint2); } }
代碼
切換到progressviewwithcircle這個moudle運行即可看到效果,有興趣的小夥伴可以看下,希望大佬們有其他更好的實現方式。