『Android自定義View實戰(zhàn)』自定義帶入場動畫的弧形百分比進度條

寫在前面

這是在簡書發(fā)表的處女座,這個想法也停留在腦海中很久了,一直拖到現在(懶癌發(fā)作2333),先自我介紹一番,一枚剛畢業(yè)不久的Android程序猿,初出茅廬的Android小生,之前一直在CSDN發(fā)表技術文章,但感覺相比之下簡書的整體體驗會稍好一些,希望能夠在簡書留下對自己技術的成長足跡,總結開發(fā)過程中的一些小小心得,這也是一個新的開始,互相學習,無量變何以質變。
?
?


正文

概述

日常開發(fā)經常會有遇到使用進度條的地方,有些場景會需要使用圓形百分比進度條來更優(yōu)雅地表示當前的進度,并賦予一些入場動畫,使得頁面更有活力(比如一些運動App,表示能量的進度條,消耗卡路里的進度條等等),給用戶一種不斷累積的視覺感:

image

?

需要定制的特性

1.設置圓弧半徑

2.背景圓弧的粗細

3.進度圓弧的粗細

4.設置進度顏色

5.中心文字大小 顏色 內容

6.進度值 最大值

7.動畫時間
?

實現思路

一共可以分為3部分來繪制: 底部的圓、進度弧線、中心文本,最終結合動畫達成效果。


1)繪制底部圓

底部繪制圓采用drawCircle(float cx, float cy, float radius, Paint paint)

代碼如下:

/**
 * 繪制后面的整圓
 */
paint.setStyle(Paint.Style.STROKE); //設置空心
paint.setStrokeWidth(bgStrokeWidth); //設置圓環(huán)的寬度
paint.setColor(roundColor);
paint.setAntiAlias(true);  //消除鋸齒
canvas.drawCircle(center, center, radius, paint);

?
?


2)繪制中心文本

中心文本采用drawText(String text, float x, float y, Paint paint)

這里需要解決一個點,如何計算文本的位置,讓文本整體居中?
可以計算整個View的中心點的坐標,可以通過Paint的 measureText 方法獲得文本的寬度,centerX-textWidth/2 即可得到文本的left,同理根據centerY - textSize/2 即可得到文本的top。

代碼如下:

/**
  * 畫進度百分比文本
*/
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(textSize);
paint.setTypeface(Typeface.DEFAULT); //設置字體
if (!TextUtils.isEmpty(centerText)) {
     //如果是設置文本內容,則直接測量文本長度并繪制
     float textWidth = paint.measureText(centerText);
     canvas.drawText(centerText, center - textWidth / 2, center + textSize / 2, paint); //畫出進度百分比
} else {
     //如果是設置百分比,則計算百分比并繪制
     int percent = (int) (((float) progressValue / (float) maxValue) * 100);  //中間的進度百分比,先轉換成float在進行除法運算,不然都為0
     float textWidth = paint.measureText(percent + "%");   //測量字體寬度,我們需要根據字體的寬度設置在圓環(huán)中間
     if (percent != 0) {
        canvas.drawText(percent + "%", center - textWidth / 2, center + textSize / 2, paint); //畫出進度百分比
     }
}

?
?


3)繪制進度弧線

從效果圖中可以看出,進度條是從底部中心開始向兩邊展開,可以通過ValueAnimator讓當前進度(接下來以curProgress代稱)從0開始增長至最終的目標進度

進度條的繪制采用 canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);
oval 弧形所在的區(qū)域,可以理解為弧形的邊界
startAngle 弧形的起始弧度 以x軸正方向為0°為起始點計算
sweepAngle 弧形的長度 以startAngle為起始點計算,順時針方向掃過的角度
useCenter 設為true時會將圓心與弧線包圍的區(qū)域也同時繪制,類似扇形效果
paint 繪制弧形的畫筆
?
畫了張示意圖方便理解:

drawArc示意圖.png

為了實現從底部向上繪制弧線,drawArcsweepAngle 肯定是(progress/max)*360,startAngle則要通過計算來動態(tài)變更。
以0°為界限,180*(curProgress/maxProgress)則表示sweepAngle的一半的長度假如當前curProgress/maxProgress 大于0.5,說明進度條弧度的一邊已經超過了0°的界限,說明進度條弧度的startAngle要小于0且超過的這部分的長度 = -(180*(curProgress/maxProgress) - 90);假如當前curProgress/maxProgress 小于0.5,說明進度條弧度的一邊未超過0°的界限,說明進度條弧度的startAngle要大于0且超過的這部分的長度 = 90 - 180*(curProgress/maxProgress);最終其實都可以采用90 - 180*(curProgress/maxProgress) 的計算得到當前的startAngle

代碼如下:

/*
* 繪制有效的進度條弧線
*/
//設置圓環(huán)的寬度
paint.setStrokeWidth(progressStrokeWidth);
//設置進度的顏色
paint.setColor(progressColor);
paint.setStrokeCap(Paint.Cap.ROUND);
//用于定義的圓弧的形狀和大小的界限
RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
paint.setStyle(Paint.Style.STROKE);
//根據進度畫圓弧
canvas.drawArc(oval, 90 -180 * ((float) progressValue / (float) maxValue), 360 * progressValue / maxValue, false, paint);

?
?


4)入場動畫

只需要不斷更新當前的progress值,從0增長到目標進度,然后不斷調用invalidate去刷新UI,代碼如下:

/**
     * 弧線動畫
     *
     * @param last    起始值
     * @param current 最終值
     * @param length  動畫時間
 */
private void setAnimation(float last, float current, int length) {
        ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, current);
        progressAnimator.setDuration(length);
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                progressValue = (int) value;
                invalidate();
            }
        });
        progressAnimator.start();
}

?
?


后續(xù)

最近有點沉迷于自定義View,其實很多看似很基礎的東西還是很重要的,底層基礎決定上層建筑,比如本篇繪制弧線的部分,如何計算出弧線的位置和長度要結合Animator來合成我們的效果,這正是其巧妙之處,雖然都說不重復造輪子,但是有時間還是要研究琢磨造造輪子,畢竟那才是真正能被自己汲取的東西。

CSDN博客IT_ZJYANG
源碼傳送門GitHub-ZJYWidget-YCircleProgressBar
里面還有很多實用的自定義View源碼及demo,會長期維護,歡迎Star~ 如有不足之處或建議還望指正,相互學習,相互進步,如果覺得不錯動動小手點個喜歡, 謝謝~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 系列文章之 Android中自定義View(一)系列文章之 Android中自定義View(二)系列文章之 And...
    YoungerDev閱讀 4,628評論 3 11
  • 導航 Android Paint之顏色過濾器 Paint之shader(圖像渲染) Paint之PathEffec...
    侯蛋蛋_閱讀 4,894評論 0 5
  • 前天有位朋友的親人得了重癥,情況非常危急!這是朋友的妻兄。朋友和他的妻子都非常焦慮難過,我們這一幫朋友也都為他們...
    關輝閱讀 360評論 2 2
  • 一、知識點 二、作業(yè) 1.計算永輝超市2017年EPS 第一步:計算 =18.17/95.7=0.19 第二步:檢...
    靜靜的頓河wj閱讀 195評論 0 0
  • 說是講三個女人的故事,其實也可以看做一個女人的故事。20歲的張艾嘉,30歲的張艾嘉和40歲的張艾嘉,換句話說,20...
    褐錦閱讀 356評論 0 0

友情鏈接更多精彩內容