Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義控件NumberCircleProgressBar(圓形進度條)的實現

Android自定義控件NumberCircleProgressBar(圓形進度條)的實現

編輯:關於Android編程

最近在Github上看到了daimajia寫的一個開源組件NumberProgressBar覺得非常好,故而在其基礎上進行了一些延伸與擴展,編寫了一個NumberCircleProgressBar(即圓形的進度條),並且分為兩種模式,我稱之為rotate模式和rising_water模式。

PS:也許本文介紹的方法不是最優(比如游戲開發中可能只需要調用一個方法即可完成),也可能會有纰漏,所以請讀者海涵!


NumberCircleProgressBar的樣圖如下:

Rotate模式

\ \

Rising_Water模式<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxicj4KPC9wPgo8cD48c3Ryb25nPjxpbWcgc3JjPQ=="/uploadfile/Collfiles/20140907/2014090709160970.gif" alt="\"> \

組件屬性

\

對於兩種不同的模式,如上圖所示,均有以下屬性:

TheCircle

  • circle_radius
  • fill_mode(name="rotate" value="0",name="rising_water" value="1" )

    The reached area and unreachedarea:

    • color
    • height

      The text area:

      • color
      • text size
      • visibility

        The bar:

        • max progress
        • current progress

          如何使用

          這個組件很小,就沒必要制作成庫了,所以使用者copy一下相關目錄下文件即可:

          1. 將src/NumberCircleProgressBar.java文件拷貝到相應目錄;

          2. 將res/values/attrs.xml中NumberCircleProgressBar的屬性定義拷貝到相應目錄;


          在布局文件中定義NumberCircleProgressBar

          
          

          在style.xml中定義NumberCircleProgressBar屬性
          
          

          在布局文件中使用style

          
          

          java代碼中使用樣例
          public void setTheNumberProgressBar() {
          
          	final NumberCircleProgressBar bnp = (NumberCircleProgressBar) findViewById(R.id.numbercircleprogress_bar);
          		timer = new Timer();
          		timer.schedule(new TimerTask() {
          			@Override
          			public void run() {
          				runOnUiThread(new Runnable() {
          					@Override
          					public void run() {
          						if (!isFinish) {
          							bnp.incrementProgressBy(2);
          							if (bnp.isFinished()) {
          								isFinish = false;
          							}
          						}
          					}
          				});
          			}
          		}, 1000, 100);
          	}

          如何實現自定義組件

          關鍵是在view的OnDraw方法中進行重繪。

          Mode Rotate 實現方式

          1.使用unreachedarea的顏色繪制Circle,作為底層;

          canvas.drawCircle(centerX, centerY,mCircleRadius, mCirclePaint);

          2.使用reacherarea的顏色繪制扇形,作為中間層;

          canvas.drawArc(mCircleRectF,DEFAULT_INITIAL_ANGLE, getProgress() * 360 / getMax(),true, mSectorPaint);

          3.使用textarea的顏色繪制文字,作為頂層;

          canvas.drawText(mCurrentDrawText,mDrawTextStart, mDrawTextEnd, mTextPaint);


          Mode Rising Water實現方法


          這裡必須要說明一下如何繪制扇形的截取部分,請看下圖:

          \

          為了繪制圖中的藍色部分,我們需要先繪制藍色部分對應的扇形,其次再繪制三角形灰色部分覆蓋藍色扇形部分(或者繪制藍色三角形補全扇形部分)。所以我們必須要知道角α,進而求出三角形中除圓心坐標外的兩點。

          如何求α?

          設p為已知的百分比,則p∈[0,1],\

          \

          聯立方程可以得到


          \

          得到方程

          \

          這裡遇到了難題,如何求超越方程的解?

          一開始我在這卡住了,在網上搜了半天,實在沒找到這類超越方程的解法。後來突然想到模擬求解啊,這不就是計算機思維的解決之道嗎?於是乎下載Mathematic軟件來進行求解:

          \

          得到了p為[0%,100%]之間的步長為1%的對應角度α的數組:

          PERCENT_TO_ARC = { 0, 0.364413d, 0.4616d,
          			0.530831d, 0.586699d, 0.634474d, 0.676734d, 0.714958d, 0.750081d,
          			0.782736d, 0.813377d, 0.842337d, 0.869872d, 0.896184d, 0.921432d,
          			0.945747d, 0.969237d, 0.991993d, 1.01409d, 1.0356d, 1.05657d,
          			1.07706d, 1.0971d, 1.11674d, 1.13601d, 1.15494d, 1.17356d,
          			1.19189d, 1.20996d, 1.22779d, 1.24539d, 1.26279d, 1.27999d,
          			1.29702d, 1.31389d, 1.33061d, 1.3472d, 1.36366d, 1.38d, 1.39625d,
          			1.4124d, 1.42847d, 1.44446d, 1.46039d, 1.47627d, 1.49209d,
          			1.50788d, 1.52364d, 1.53937d, 1.55509d, 0.5 * Math.PI, 1.58651d,
          			1.60222d, 1.61796d, 1.63371d, 1.6495d, 1.66533d, 1.6812d, 1.69713d,
          			1.71313d, 1.72919d, 1.74535d, 1.76159d, 1.77794d, 1.7944d,
          			1.81098d, 1.8277d, 1.84457d, 1.8616d, 1.8788d, 1.8962d, 1.9138d,
          			1.93163d, 1.9497d, 1.96803d, 1.98665d, 2.00558d, 2.02485d,
          			2.04449d, 2.06454d, 2.08502d, 2.10599d, 2.1275d, 2.1496d, 2.17236d,
          			2.19585d, 2.22016d, 2.24541d, 2.27172d, 2.29926d, 2.32822d,
          			2.35886d, 2.39151d, 2.42663d, 2.46486d, 2.50712d, 2.55489d,
          			2.61076d, 2.67999d, 2.77718d, Math.PI };
          


          得到了角度α,那麼成功近在咫尺了:

          1. 使用unreachedarea的顏色繪制Circle,作為底層;

          2. 使用reacherarea的顏色繪制扇形,作為中間層;

          3. 當percent∈[0,50%]時,使用unreached area的顏色繪制三角形覆蓋扇形相應位置;

          當percent∈[50%,100%]時,使用reached area的顏色繪制三角形填充扇形相應位置;

          1. 使用textarea的顏色繪制文字,作為頂層;

          大功告成,但此時觀察Demo程序,發現還是有點瑕疵。

          三角形沒有完全覆蓋扇形的那部分面積,留下了兩條邊線隱約可以看到底層扇形的顏色,而且在使用Visio繪制文檔中圖例時也出現了這種情況!!

          查找了半天,實在沒發現哪有什麼錯誤的地方。最終只得使用一點實際的辦法了——以一定粗度的實線繪制三角形的兩條邊,覆蓋透出的顏色。這也許不是正確的方案,但解決了問題,如果讀者有更好的辦法或者知道此bug的出處,希望告知!

          這裡要贊一下騰訊的應用寶,手機沒有root,無法使用截屏軟件來制作gif,而應用寶裡有動態截屏制作gif,有點不足的地方就是需要手動點,如果有設幀率的地方就更好了!

          工程源代碼

          It’s Over!




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved