1. 程式人生 > >CircleNumberProgressBar:顯示數字的圓形進度條

CircleNumberProgressBar:顯示數字的圓形進度條

圓形的ProgressBar是經常使用的控制元件,能夠顯示當前的進度,但有時候可能還不夠直觀,原有控制元件顯示進度時並不能準確的知道當前進度是多少,又或是遇到專案需求需要在進度條中間加上數字顯示,嗯……專案需求,所以這個時候就需要自己對原有的ProgressBar進行改造了,自己動手,豐衣足食嘛!

在原有的ProgressBar的基礎上進行改造,那麼就新建一個類CircleNumberProgressBar,並讓其繼承ProgressBar,接著我們需要先定義好CircleNumberProgressBar需要的相關屬性

  <declare-styleable name="CircleNumberProgressBar">

      <!-- 圓的半徑 -->
      <attr name="cnpb_circle_radius" format="dimension"/>

      <!-- 進度條的寬度 -->
      <attr name="cnpb_bar_width" format="dimension" />

      <!-- 達到的進度顏色 -->
      <attr name="cnpb_reach_color" format="color" />

      <!-- 未達到的進度顏色 -->
      <attr name="cnpb_unreach_color" format="color" />

      <!-- 文字大小 -->
      <attr name="cnpb_text_size" format="dimension" />

      <!-- 文字顏色 -->
      <attr name="cnpb_text_color" format="color" />

      <!-- 文字是否顯示 -->
      <attr name="cnpb_text_visibility" format="enum">
          <enum name="invisible" value="0"/>
          <enum name="visible" value="1"/>
      </attr>

      <!-- 單位 -->
      <attr name="cnpb_unit" format="string"/>

      <!-- 單位是否顯示 -->
      <attr name="cnpb_unit_visibility" format="enum">
          <enum name="invisible" value="0"/>
          <enum name="visible" value="1"/>
      </attr>

  </declare-styleable>

我們還可以定義一個設定CircleNumberProgressBarStyle的一個屬性

<attr name="styleCircleNumberProgressBar" format="reference" />

這樣可以方便我們在styles檔案中對CircleNumberProgressBar的屬性進行統一設定,例如

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="styleCircleNumberProgressBar">@style/CircleNumberProgressBarTheme</item>
</style>

好了,定義並設定好屬性之後,就需要在程式碼檔案中對這些屬性進行取值設定了,在建構函式中使用TypedArray對申明的屬性進行取值,並在建構函式中對畫筆Paint進行一些相關屬性的設定

public CircleNumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleNumberProgressBar, defStyleAttr, R.style.CircleNumberProgressBar_Style);

    mRadius = typedArray.getDimensionPixelSize(R.styleable.CircleNumberProgressBar_cnpb_circle_radius, dp2px(30));

    mBarWidth = typedArray.getDimensionPixelSize(R.styleable.CircleNumberProgressBar_cnpb_bar_width, dp2px(8));

    mReachColor = typedArray.getColor(R.styleable.CircleNumberProgressBar_cnpb_reach_color, 0xFF303F9F);

    mUnReachColor = typedArray.getColor(R.styleable.CircleNumberProgressBar_cnpb_unreach_color, 0xFFD3D6DA);

    mTextSize = typedArray.getDimensionPixelSize(R.styleable.CircleNumberProgressBar_cnpb_text_size, sp2px(14));

    mTextColor = typedArray.getColor(R.styleable.CircleNumberProgressBar_cnpb_text_color, 0xFF303F9F);

    mTextVisibility = typedArray.getInt(R.styleable.CircleNumberProgressBar_cnpb_text_visibility, VISIBLE);

    mUnit = typedArray.getString(R.styleable.CircleNumberProgressBar_cnpb_unit);

    mUnitVisibility = typedArray.getInt(R.styleable.CircleNumberProgressBar_cnpb_unit_visibility, VISIBLE);

    typedArray.recycle();

    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setStrokeCap(Paint.Cap.ROUND);

    rectF = new RectF(0, 0, mRadius * 2, mRadius * 2);

    mBound = new Rect();
}

設定屬性之後,就到了自定義View的重點了,需要重寫onMeasure()onDraw()方法,在onMeasure()方法中需要對View進行測量,從而確定View的測量寬高,在CircleNumberProgressBar中,onMeasure()裡面的測量程式碼如下

@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

    int width = 0;
    int height = 0;

    switch (widthSpecMode) {
        case MeasureSpec.AT_MOST :
            width = Math.min(mRadius * 2 + getPaddingLeft() + getPaddingRight() + mBarWidth, widthSpecSize);
            break;

        case MeasureSpec.EXACTLY :
            width = widthSpecSize;
            break;

        case MeasureSpec.UNSPECIFIED :
            width = mRadius * 2 + getPaddingRight() + getPaddingLeft() + mBarWidth;
            break;
    }

    switch (heightSpecMode) {
        case MeasureSpec.AT_MOST :
            height = Math.min(mRadius * 2 + getPaddingTop() + getPaddingBottom() + mBarWidth, heightSpecSize);
            break;

        case MeasureSpec.EXACTLY :
            height = heightSpecSize;
            break;

        case MeasureSpec.UNSPECIFIED :
            height = mRadius * 2 + getPaddingTop() + getPaddingBottom() + mBarWidth;
            break;
    }

    int result = Math.min(width, height);

    setMeasuredDimension(result, result);
}

在這裡,會先分別獲取寬高的測量模式SpecMode和對應測量模式下的規格大小SpecSize,接著會對測量模式SpecMode進行判定,並通過計算獲取真正的寬高值,要注意的是,在計算時要把padding值算進去,否則會出現誤差,在確定好寬高之後,再呼叫setMeasuredDimension方法設定寬高,這樣就能確定View的大小了

測量了View的大小後,就要對View進行繪製了,我們需要繪製圓形,圓弧和文字,圓形是用來顯示沒有達到的進度,圓弧是顯示達到的進度,文字則是在中間顯示的進度值,看看程式碼

@Override
protected synchronized void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    String text = mUnitVisibility == VISIBLE ? getProgress() + mUnit : getProgress() + "";
    float baseline = getMeasuredHeight() / 2 + mPaint.getTextSize() / 2 - mPaint.getFontMetrics().descent - getPaddingTop();
    canvas.save();
    canvas.translate(getPaddingLeft() + mBarWidth / 2, getPaddingTop() + mBarWidth / 2);
    mPaint.setStyle(Paint.Style.STROKE);

    //先繪製未達到的進度條
    mPaint.setColor(mUnReachColor);
    mPaint.setStrokeWidth(mBarWidth);
    canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);

    //再繪製已經達到的進度條
    mPaint.setColor(mReachColor);
    mPaint.setStrokeWidth(mBarWidth);
    float angle = getProgress() * 1.0f / getMax() * 360;
    canvas.drawArc(rectF, 0, angle, false, mPaint);

    //繪製文字
    if (mTextVisibility == VISIBLE) {
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mTextColor);
        mPaint.setTextSize(mTextSize);
        mPaint.getTextBounds(text, 0, text.length(), mBound);
        canvas.drawText(text, mRadius - mBound.width() / 2, baseline, mPaint);
    }

    canvas.restore();

}

在繪製時,需要先呼叫canvas.save()方法儲存畫布狀態,以免影響後續操作。在繪製圓形時,需要設定畫筆的StyleSTROKE表示空心,再呼叫canvas.drawCircle方法繪製圓形,其圓心的x,y座標和半徑都是一樣的

接著繪製進度條,這裡是要繪製圓弧了,再繪製之前需要先計算圓弧的角度,這個比較簡單,根據當前值 / 最大值 * 360的公式計算就可以了,在繪製圓弧時引數還需要一個RectF,這是用來指定繪製圓弧的外部巨星區域,這個只要設定其長高為半徑的兩倍就可以了rectF = new RectF(0, 0, mRadius * 2, mRadius * 2);

最後是繪製文字,繪製文字時要將畫筆的Style設定為FILL,接著我們需要知道文字的寬度,可以通過呼叫mPaint.getTextBounds方法先獲取到文字的邊界,再確定寬度,注意的是在canvas.drawText的方法中,第三個引數y是表示文字的基線baseline在螢幕上的位置,所以要先計算基線baseline的高,這樣才能把文字準確的繪製

繪製完成後就可進行使用啦,直接在xml檔案上進行呼叫就可以了

<com.zht.circlenumberprogressbar.widget.CircleNumberProgressBar
    android:id="@+id/cnpb_progress"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    app:cnpb_circle_radius="50dp" />

屬性值可以直接在xml檔案設定,也可以在styles檔案進行設定

<style name="CircleNumberProgressBarTheme" parent="CircleNumberProgressBar.Style">
    <item name="cnpb_text_color">#FF303F9F</item>
    <item name="cnpb_reach_color">#FF303F9F</item>
    <item name="cnpb_unreach_color">#FFD3D6DA</item>
    <item name="cnpb_text_size">16sp</item>
    <item name="cnpb_text_color">#FF303F9F</item>
    <item name="cnpb_text_visibility">visible</item>
    <item name="cnpb_unit">%</item>
    <item name="cnpb_unit_visibility">visible</item>
</style>

相關推薦

CircleNumberProgressBar顯示數字圓形進度

圓形的ProgressBar是經常使用的控制元件,能夠顯示當前的進度,但有時候可能還不夠直觀,原有控制元件顯示進度時並不能準確的知道當前進度是多少,又或是遇到專案需求需要在進度條中間加上數字顯示,嗯……專案需求,所以這個時候就需要自己對原有的Progress

HTML5效果Canvas 實現圓形進度顯示數字百分比

實現效果 1.首先建立html程式碼 <canvas id="canvas" width="500" he

異步下載圓形進度顯示進度

https ati ack blog nbsp idt 進度 circle osi 圓形進度條參考鏈接即可:使用css3實現圓形進度條 需求點擊下載後遮罩層顯示下載進度: 1.圓形進度條參考以上鏈接,有點小瑕疵,可更改定位距離實現重合。 2.遮罩層: .lbOverla

Canvas實現多個圓形進度顯示百分比,並繫結各自的click事件

Canvas實現多個圓形進度條顯示百分比,並繫結各自的click事件 目錄 Canvas實現多個圓形進度條顯示百分比並繫結各自的click事件 目錄 實現效果 製

微信小程式靜態圓形進度實現

效果圖: 實現: function drawCircleProgress(canvasId, backStrokeColor,strokeColor,x,y,radius,percent,text,fontSize,fontColor){ // console.l

帶動畫效果的圓形進度顯示定時器倒計時

在實際專案開發中我們經常要使用進度條監聽下載進度,使用的大多是在UIView中的- (void)drawRect:(CGRect)rect方法中描繪圓形路徑,然後通過傳過來的進度值計算圓形路徑百分比達到監聽效果,這種監聽進度方法適合檔案下載,但是我們開發中有時會

微信小程式開發實時圓形進度實現

第九程式給大家帶來微信小程式開發:實時圓形進度條實現,希望大家在開發小程式過程中能夠幫助大家解決。 廢話不多說,先上一張效果圖! 實現思路 建立兩個canvas標籤,先繪製底層的淺灰色圓圈背景,再繪製上層的紅色進度條。 WXML程式碼              開始動

Android動畫篇(一)圓形進度CircleProgressBar

前言 最近看框架和原始碼比較多,很久沒有寫動畫了,相信很多的朋友都對動畫感興趣,我也不例外,畢竟做前端還是要靠動畫特效吃飯的,並且比寫功能模組更有成就感。 今天我們就來個稍微簡單一點的CircleProgressBar熱個身。 首先需要對ValueAnim

canvas 繪制圓形進度

設置字體大小 文字 height center body 字體 指定位置 str n) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

純CSS3制作圓形進度所遇到的問題

order 我們 消失 樣式 近日 內部 右上角 圓形進度 spa   近日在開發的頁面中,需要制作一個動態的圓形進度條,首先想到的是利用兩個矩形,寬等於直徑的一半,高等於直徑,兩個矩形利用浮動貼在一起,設置overflow:hidden屬性,作為盒子,內部有一個與其寬高相

圓形進度

最小 element ali logs isp ber per 圖片 center 基於angularJS1/jquery和radialIndicator插件 效果圖: 1、首先引入一下文件: 2、在jsp中引入需要的文件 <script src="js

CARVARS 圓形進度

sele int 20px 進度 arc null type eight 進度條 <!DOCTYPE html><html><head><meta charset="UTF-8"><title></title

vue慕課網音樂項目手記30-音樂環形進度的實現

http .org ogre bar clas VG round 慕課網 TE 環形進度條是基於svg實現的。 <template> <div class="progress-circle"> <svg :width

圓形進度是學習

學習網站:http://www.cnblogs.com/jr1993/p/4677921.html CSS:     *{               

Android控制元件之圓形進度

Android-自定義ProgressBar實現圓弧進度條 在之前的專案中用到過這個,感覺還是非常實用的,我實現的是額度的增長. 繼承於ProgressBar實現,保留了Progressbar的特性,原始碼在文尾。

白鷺egret專案資源的loading,介面的顯示與載入進度:ProgressBar;

1.用egret建立一個空的euigame專案; 2.點選f5執行空的專案[他自帶了一個載入的txt顯示]; EE:資源太少,載入速度太快,童鞋們可能注意不到; 然後,我們在egretwing的資源路徑加如下倆資料夾; loading【放載入介面用的圖片】和Pic【放測試loa

使用自定義View繪製圓形進度效果

首先自定義屬性 res - values - attrs(自己建立): <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyCicle">

Python中製作帶數字進度

簡單製作一個進度條,效果如下: 不多說,直接上程式碼: import time EACH_STEP_COST_TIME = 0.3 PROCESS_TOTAL_STEP = 40 def process_bar(current_state, total_state, bar_l

自定義View實現圓形進度跳轉頁面

效果: //首先在values資料夾下建立一個attrs.xml: ?xml version=“1.0” encoding=“utf-8”?> //佈局: <?xml version="1.0" encoding="utf-8"?>

基於canvas的圓形進度

建立HTML檔案,CSS檔案和JavaScript檔案,並引入jquery。 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" con