天天看點

Android自定義控件:進度條的四種實作方式

版權聲明:本文為部落客原創文章,轉載請标明出處。 https://blog.csdn.net/chaoyu168/article/details/50722935

前三種實作方式代碼出自:

http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/

(源碼下載下傳)

http://download.csdn.net/detail/chaoyu168/9616035

最近一直在學習自定義控件,搜了許多大牛們Blog裡分享的小教程,也上GitHub找了一些類似的控件進行學習。發現讀起來都不太好懂,就想寫這麼一篇東西作為學習筆記吧。

一、控件介紹:

進度條在App中非常常見,例如下載下傳進度、加載圖檔、打開文章、打開網頁等等……都需要這麼一個效果讓使用者知道我們的App正在讀取,以構造良好的互動。如果沒有這樣一個效果的話,使用者沒法知道東西有沒有下載下傳好、圖檔加載了沒有、文章打開了沒……會讓使用者很不爽。基于這樣的情景我們的UI設計師們創造了這樣一個控件。

二、這篇文章會涉及的知識點:

跟我一樣剛入門的Android菜鳥們,我推薦大家先了解一下這些知識點再往下看。這些知識點我也會推薦一些部落格給大家看看,更推薦大家看文檔裡的解釋,當然大牛們可以直接無視……

1、ClipDrawable類:能夠對一個drawable類進行剪切操作(即隻顯示某一部分的區域,另一部分隐藏),顯示多大的區域由level控制(level取值是0~10000)

【部落格:http://blog.csdn.net/lonelyroamer/article/details/8244777】、沒文檔的可以在這看【http://www.apihome.cn/api/android/ClipDrawable.html】

2、自定義View:guolin大神的深入學習View四部曲

Android

LayoutInflater原理分析,帶你一步步深入了解View

——http://blog.csdn.net/guolin_blog/article/details/12921889】 Android視圖繪制流程完全解析,帶你一步步深入了解View ——http://blog.csdn.net/guolin_blog/article/details/16330267】 Android視圖狀态及重繪流程分析,帶你一步步深入了解View ——http://blog.csdn.net/guolin_blog/article/details/17045157】 Android自定義View的實作方法,帶你一步步深入了解View

——http://blog.csdn.net/guolin_blog/article/details/17357967】

3、沒看過我寫的:Android自定義控件——老版優酷三級菜單的話,或許需要看看這個:

【RotateAnimation詳解——http://blog.csdn.net/u012403246/article/details/41415799】

三、Android上的實作方式:

(前三種方法比較簡單,第四種方法是GitHub項目的解析,對前三種沒興趣可以直接跳到後邊……)

1、效果圖:

将進度條的變換過程分解為一幀一幀的圖檔,将這些一幀一幀的圖檔連起來構成一個動畫。常用于:手機閱讀網頁、逛社群時,加載圖檔、文章等不需要清楚知道加載進度,但是需要知道是否進行加載的情景。

這種方法實作可以通過建立一個animation-list的XML檔案,然後給系統API提供的ProgressBar的indeterminateDrawable屬性就可以了。(這個屬性應該是類似于設定一個動畫吧……)

XML:

[html] 

view

plain

copy https://code.csdn.net/snippets/627396 https://code.csdn.net/snippets/627396/fork

  1. <?xml version="1.0" encoding="utf-8"?>    
  2. <animation-list xmlns:android="http://schemas.android.com/apk/res/android"    
  3.     android:oneshot="false" >    
  4.     <item android:duration="150" >    
  5.         <clip     
  6.             android:clipOrientation="horizontal"    
  7.             android:drawable="@drawable/loading_01"    
  8.             android:gravity="left"/>    
  9.     </item>    
  10.             android:drawable="@drawable/loading_02"    
  11.             android:drawable="@drawable/loading_03"    
  12.             android:drawable="@drawable/loading_04"    
  13.             android:drawable="@drawable/loading_05"    
  14.             android:drawable="@drawable/loading_06"    
  15.             android:drawable="@drawable/loading_07"    
  16.             android:drawable="@drawable/loading_08"    
  17.             android:drawable="@drawable/loading_09"    
  18.             android:drawable="@drawable/loading_10"    
  19.             android:drawable="@drawable/loading_11"    
  20.             android:drawable="@drawable/loading_12"    
  21. </animation-list>  
https://code.csdn.net/snippets/627396 https://code.csdn.net/snippets/627396/fork
  1. <ProgressBar     
  2.     android:layout_width="wrap_content"    
  3.     android:layout_height="wrap_content"    
  4.     android:indeterminateDrawable="@drawable/progressbar1"    
  5.     />  

2、效果圖:

在上一篇有關自定義控件的部落格裡我們使用了一個RotateAnimation類來實作旋轉效果 (http://blog.csdn.net/u012403246/article/details/41309161),其實,我們在這裡也可以把一張圖檔,通過旋轉,達到我們要的效果。本質上和上一種方法沒多大差別。

我們隻需要建立一個rotate的XML,對其屬性進行一些簡單的設定,然後加入我們要用的圖檔就可以了。

https://code.csdn.net/snippets/627396 https://code.csdn.net/snippets/627396/fork
  1. <rotate xmlns:android="http://schemas.android.com/apk/res/android"    
  2.     android:pivotX="50%"    
  3.     android:pivotY="50%"    
  4.     android:fromDegrees="0"    
  5.     android:toDegrees="360"    
  6.     android:interpolator="@android:anim/accelerate_decelerate_interpolator" >    
  7.     <bitmap     
  8.         android:antialias="true"    
  9.         android:filter="true"    
  10.         android:src="@drawable/loading_360"/>    
  11. </rotate>  
https://code.csdn.net/snippets/627396 https://code.csdn.net/snippets/627396/fork
  1.     android:indeterminateDrawable="@drawable/progressbar2"/>  

3、效果圖:

我們可以弄兩張照片,第一張是純黑色的,然後把這張照片中心挖一個圓出來,圓區域弄成白色,挖出來的圓弄成第二張照片。我們不妨疊加顯示兩張照片,剛開始把第二張完全“遮住”,随着加載進度的增加,我們減少遮住的區域把第二張照片慢慢的顯示出來。

Android上剛好就有這麼一個ClipDrawable類,能夠實作剪裁的過程。我們來看看怎麼通過這樣的方式自定義一個進度條控件。

代碼:

[java] 

https://code.csdn.net/snippets/627396 https://code.csdn.net/snippets/627396/fork
  1. public class MyProgressBar extends FrameLayout{    
  2.     private boolean running;    
  3.     private int progress = 0;    
  4.     private static final int MAX_PROGRESS = 10000;    
  5.     private ClipDrawable clip;    
  6.     private Handler handler = new Handler(){    
  7.         @Override    
  8.         public void handleMessage(android.os.Message msg) {    
  9.             if(msg.what == 0x123)    
  10.                 clip.setLevel(progress);    
  11.         }    
  12.     };    
  13.     public MyProgressBar(Context context){    
  14.         this(context,null,0);    
  15.     }    
  16.     public MyProgressBar(Context context,AttributeSet attrs){    
  17.     public MyProgressBar(Context context, AttributeSet attrs, int defStyle) {    
  18.         super(context, attrs, defStyle);    
  19.         Init(context);    
  20.     public void Init(Context context){    
  21.         View view = LayoutInflater.from(context).inflate(R.layout.view, null);    
  22.         ImageView iv = (ImageView)view.findViewById(R.id.progress_img);    
  23.         addView(view);    
  24.         clip = (ClipDrawable)iv.getDrawable();    
  25.         Thread thread = new Thread(new Runnable() {    
  26.             @Override    
  27.             public void run() {    
  28.                 running = true;    
  29.                 while(running){    
  30.                     handler.sendEmptyMessage(0x123);    
  31.                     if(progress == MAX_PROGRESS)    
  32.                         progress = 0;    
  33.                     progress += 100;    
  34.                     try {    
  35.                         Thread.sleep(18);    
  36.                     } catch (InterruptedException e) {    
  37.                         e.printStackTrace();    
  38.                     }    
  39.                 }    
  40.             }    
  41.         });    
  42.         thread.start();    
  43.     public void stop(){    
  44.         progress = 0;    
  45.         running = false;    
  46. }   

通過代碼我們可以看到,邏輯非常簡單,關鍵就在于ClipDrawable的setLevel()方法,這個是設定剪裁效果的。

4、效果圖:

實作一個View的子類——Progress Wheel類,實作進度條效果。具體的内容我都寫在了注釋上,如果不了解自定義控件的知識,可以去閱讀guolin部落格裡自定義View四部曲的講解,講的挺好的。

https://code.csdn.net/snippets/627396 https://code.csdn.net/snippets/627396/fork
  1. public class ProgressWheel extends View {    
  2.     //繪制View用到的各種長、寬帶大小    
  3.     private int layout_height = 0;    
  4.     private int layout_width = 0;    
  5.     private int fullRadius = 100;    
  6.     private int circleRadius = 80;    
  7.     private int barLength = 60;    
  8.     private int barWidth = 20;    
  9.     private int rimWidth = 20;    
  10.     private int textSize = 20;    
  11.     private float contourSize = 0;    
  12.     //與頁邊的間距    
  13.     private int paddingTop = 5;    
  14.     private int paddingBottom = 5;    
  15.     private int paddingLeft = 5;    
  16.     private int paddingRight = 5;    
  17.     //View要繪制的顔色    
  18.     private int barColor = 0xAA000000;    
  19.     private int contourColor = 0xAA000000;    
  20.     private int circleColor = 0x00000000;    
  21.     private int rimColor = 0xAADDDDDD;    
  22.     private int textColor = 0xFF000000;    
  23.     //繪制要用的畫筆    
  24.     private Paint barPaint = new Paint();    
  25.     private Paint circlePaint = new Paint();    
  26.     private Paint rimPaint = new Paint();    
  27.     private Paint textPaint = new Paint();    
  28.     private Paint contourPaint = new Paint();    
  29.     //繪制要用的矩形    
  30.     @SuppressWarnings("unused")    
  31.     private RectF rectBounds = new RectF();    
  32.     private RectF circleBounds = new RectF();    
  33.     private RectF circleOuterContour = new RectF();    
  34.     private RectF circleInnerContour = new RectF();    
  35.     //動畫    
  36.     //每次繪制要移動的像素數目    
  37.     private int spinSpeed = 2;    
  38.     //繪制過程的時間間隔    
  39.     private int delayMillis = 0;    
  40.     int progress = 0;    
  41.     boolean isSpinning = false;    
  42.     //其他    
  43.     private String text = "";    
  44.     private String[] splitText = {};    
  45.     /**  
  46.      * ProgressWheel的構造方法  
  47.      *  
  48.      * @param context  
  49.      * @param attrs  
  50.      */    
  51.     public ProgressWheel(Context context, AttributeSet attrs) {    
  52.         super(context, attrs);    
  53.         parseAttributes(context.obtainStyledAttributes(attrs,    
  54.                 R.styleable.ProgressWheel));    
  55.     //----------------------------------    
  56.     //初始化一些元素    
  57.     /*  
  58.      * 調用這個方法時,使View繪制為方形  
  59.      * From: http://www.jayway.com/2012/12/12/creating-custom-android-views-part-4-measuring-and-how-to-force-a-view-to-be-square/  
  60.      *   
  61.     @Override    
  62.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
  63.         // 首先我們要調用超類的onMeasure借口     
  64.         // 原因是我們自己去實作一個方法獲得長度、寬度太麻煩了    
  65.         // 使用超類的的方法非常友善而且讓複雜的細節可控    
  66.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);    
  67.         // 在這裡我們不能使用getWidth()和getHeight()。     
  68.         // 因為這兩個方法隻能在View的布局完成後才能使用,而一個View的繪制過程是先繪制元素,再繪制Layout    
  69.         // 是以我們必須使用getMeasuredWidth()和getMeasuredHeight()    
  70.         int size = 0;    
  71.         int width = getMeasuredWidth();    
  72.         int height = getMeasuredHeight();    
  73.         int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();    
  74.         int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom();    
  75.         // 最後我們用一些簡單的邏輯去計算View的大小并調用setMeasuredDimension()去設定View的大小    
  76.         // 在比較View的長寬前我們不考慮間距,但當我們設定View所需要繪制的面積時,我們要考慮它    
  77.         // 不考慮間距的View(View内的實際畫面)此時就應該是方形的,但是由于間距的存在,最終View所占的面積可能不是方形的     
  78.         if (widthWithoutPadding > heigthWithoutPadding) {    
  79.             size = heigthWithoutPadding;    
  80.         } else {    
  81.             size = widthWithoutPadding;    
  82.         // 如果你重寫了onMeasure()方法,你必須調用setMeasuredDimension()方法     
  83.         // 這是你設定View大小的唯一途徑      
  84.         // 如果你不調用setMeasuredDimension()方法,父控件會抛出異常,并且程式會崩潰    
  85.         // 如果我們使用了超類的onMeasure()方法,我們就不是那麼需要setMeasuredDimension()方法    
  86.         // 然而,重寫onMeasure()方法是為了改變既有的繪制流程,是以我們必須調用setMeasuredDimension()方法以達到我們的目的    
  87.         setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size + getPaddingTop() + getPaddingBottom());    
  88.      * 使用onSizeChanged方法代替onAttachedToWindow獲得View的面積  
  89.      * 因為這個方法會在測量了MATCH_PARENT和WRAP_CONTENT後馬上被調用  
  90.      * 使用獲得的面積設定View  
  91.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {    
  92.         super.onSizeChanged(w, h, oldw, oldh);    
  93.         // Share the dimensions    
  94.         layout_width = w;    
  95.         layout_height = h;    
  96.         setupBounds();    
  97.         setupPaints();    
  98.         invalidate();    
  99.      * 設定我們想要繪制的progress wheel的顔色  
  100.     private void setupPaints() {    
  101.         barPaint.setColor(barColor);    
  102.         barPaint.setAntiAlias(true);    
  103.         barPaint.setStyle(Style.STROKE);    
  104.         barPaint.setStrokeWidth(barWidth);    
  105.         rimPaint.setColor(rimColor);    
  106.         rimPaint.setAntiAlias(true);    
  107.         rimPaint.setStyle(Style.STROKE);    
  108.         rimPaint.setStrokeWidth(rimWidth);    
  109.         circlePaint.setColor(circleColor);    
  110.         circlePaint.setAntiAlias(true);    
  111.         circlePaint.setStyle(Style.FILL);    
  112.         textPaint.setColor(textColor);    
  113.         textPaint.setStyle(Style.FILL);    
  114.         textPaint.setAntiAlias(true);    
  115.         textPaint.setTextSize(textSize);    
  116.         contourPaint.setColor(contourColor);    
  117.         contourPaint.setAntiAlias(true);    
  118.         contourPaint.setStyle(Style.STROKE);    
  119.         contourPaint.setStrokeWidth(contourSize);    
  120.      * 設定元素的邊界  
  121.     private void setupBounds() {    
  122.         // 為了保持寬度和長度的一緻,我們要獲得layout_width和layout_height中較小的一個,進而繪制一個圓    
  123.         int minValue = Math.min(layout_width, layout_height);    
  124.         // 計算在繪制過程中在x,y方向的偏移量    
  125.         int xOffset = layout_width - minValue;    
  126.         int yOffset = layout_height - minValue;    
  127.         // 間距加上偏移量    
  128.         paddingTop = this.getPaddingTop() + (yOffset / 2);    
  129.         paddingBottom = this.getPaddingBottom() + (yOffset / 2);    
  130.         paddingLeft = this.getPaddingLeft() + (xOffset / 2);    
  131.         paddingRight = this.getPaddingRight() + (xOffset / 2);    
  132.         int width = getWidth(); //this.getLayoutParams().width;    
  133.         int height = getHeight(); //this.getLayoutParams().height;    
  134.         rectBounds = new RectF(paddingLeft,    
  135.                 paddingTop,    
  136.                 width - paddingRight,    
  137.                 height - paddingBottom);    
  138.         circleBounds = new RectF(paddingLeft + barWidth,    
  139.                 paddingTop + barWidth,    
  140.                 width - paddingRight - barWidth,    
  141.                 height - paddingBottom - barWidth);    
  142.         circleInnerContour = new RectF(circleBounds.left + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.top + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.right - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.bottom - (rimWidth / 2.0f) - (contourSize / 2.0f));    
  143.         circleOuterContour = new RectF(circleBounds.left - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.top - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.right + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.bottom + (rimWidth / 2.0f) + (contourSize / 2.0f));    
  144.         fullRadius = (width - paddingRight - barWidth) / 2;    
  145.         circleRadius = (fullRadius - barWidth) + 1;    
  146.      * 從XML中解析控件的屬性  
  147.      * @param a the attributes to parse  
  148.     private void parseAttributes(TypedArray a) {    
  149.         barWidth = (int) a.getDimension(R.styleable.ProgressWheel_barWidth,    
  150.                 barWidth);    
  151.         rimWidth = (int) a.getDimension(R.styleable.ProgressWheel_rimWidth,    
  152.                 rimWidth);    
  153.         spinSpeed = (int) a.getDimension(R.styleable.ProgressWheel_spinSpeed,    
  154.                 spinSpeed);    
  155.         delayMillis = a.getInteger(R.styleable.ProgressWheel_delayMillis,    
  156.                 delayMillis);    
  157.         if (delayMillis < 0) {    
  158.             delayMillis = 0;    
  159.         barColor = a.getColor(R.styleable.ProgressWheel_barColor, barColor);    
  160.         barLength = (int) a.getDimension(R.styleable.ProgressWheel_barLength,    
  161.                 barLength);    
  162.         textSize = (int) a.getDimension(R.styleable.ProgressWheel_textSize,    
  163.                 textSize);    
  164.         textColor = (int) a.getColor(R.styleable.ProgressWheel_textColor,    
  165.                 textColor);    
  166.         //如果text是空的,就無視它    
  167.         if (a.hasValue(R.styleable.ProgressWheel_text)) {    
  168.             setText(a.getString(R.styleable.ProgressWheel_text));    
  169.         rimColor = (int) a.getColor(R.styleable.ProgressWheel_rimColor,    
  170.                 rimColor);    
  171.         circleColor = (int) a.getColor(R.styleable.ProgressWheel_circleColor,    
  172.                 circleColor);    
  173.         contourColor = a.getColor(R.styleable.ProgressWheel_contourColor, contourColor);    
  174.         contourSize = a.getDimension(R.styleable.ProgressWheel_contourSize, contourSize);    
  175.         // 使用TypedArray獲得控件屬性時必須要注意:使用結束後必須回收TypedArray的對象    
  176.         a.recycle();    
  177.     protected void onDraw(Canvas canvas) {    
  178.         super.onDraw(canvas);    
  179.         //繪制内圓    
  180.         canvas.drawArc(circleBounds, 360, 360, false, circlePaint);    
  181.         //繪制邊界    
  182.         canvas.drawArc(circleBounds, 360, 360, false, rimPaint);    
  183.         canvas.drawArc(circleOuterContour, 360, 360, false, contourPaint);    
  184.         canvas.drawArc(circleInnerContour, 360, 360, false, contourPaint);    
  185.         //繪制條紋    
  186.         if (isSpinning) {    
  187.             canvas.drawArc(circleBounds, progress - 90, barLength, false,    
  188.                     barPaint);    
  189.             canvas.drawArc(circleBounds, -90, progress, false, barPaint);    
  190.         //繪制我們想要設定的文字 (并讓它顯示在圓水準和垂直方向的中心處)    
  191.         float textHeight = textPaint.descent() - textPaint.ascent();    
  192.         float verticalTextOffset = (textHeight / 2) - textPaint.descent();    
  193.         for (String s : splitText) {    
  194.             float horizontalTextOffset = textPaint.measureText(s) / 2;    
  195.             canvas.drawText(s, this.getWidth() / 2 - horizontalTextOffset,    
  196.                     this.getHeight() / 2 + verticalTextOffset, textPaint);    
  197.             scheduleRedraw();    
  198.     private void scheduleRedraw() {    
  199.         progress += spinSpeed;    
  200.         if (progress > 360) {    
  201.             progress = 0;    
  202.         postInvalidateDelayed(delayMillis);    
  203.     *   判斷wheel是否在旋轉  
  204.     */    
  205.     public boolean isSpinning() {    
  206.         if(isSpinning){    
  207.             return true;    
  208.             return false;    
  209.      * 重設進度條的值  
  210.     public void resetCount() {    
  211.         setText("0%");    
  212.      * 停止進度條的旋轉  
  213.     public void stopSpinning() {    
  214.         isSpinning = false;    
  215.         postInvalidate();    
  216.      * 讓進度條開啟旋轉模式  
  217.     public void spin() {    
  218.         isSpinning = true;    
  219.      * 讓進度條每次增加1(最大值為360)  
  220.     public void incrementProgress() {    
  221.         progress++;    
  222.         if (progress > 360)    
  223.         setText(Math.round(((float) progress / 360) * 100) + "%");    
  224.        postInvalidate();    
  225.      * 設定進度條為一個确切的數值  
  226.     public void setProgress(int i) {    
  227.         progress = i;    
  228.     //get和set方法    
  229.      * 設定progress bar的文字并不需要重新整理View  
  230.      * @param text the text to show ('\n' constitutes a new line)  
  231.     public void setText(String text) {    
  232.         this.text = text;    
  233.         splitText = this.text.split("\n");    
  234.     public int getCircleRadius() {    
  235.         return circleRadius;    
  236.     public void setCircleRadius(int circleRadius) {    
  237.         this.circleRadius = circleRadius;    
  238.     public int getBarLength() {    
  239.         return barLength;    
  240.     public void setBarLength(int barLength) {    
  241.         this.barLength = barLength;    
  242.     public int getBarWidth() {    
  243.         return barWidth;    
  244.     public void setBarWidth(int barWidth) {    
  245.         this.barWidth = barWidth;    
  246.         if ( this.barPaint != null ) {    
  247.             this.barPaint.setStrokeWidth( this.barWidth );    
  248.     public int getTextSize() {    
  249.         return textSize;    
  250.     public void setTextSize(int textSize) {    
  251.         this.textSize = textSize;    
  252.         if ( this.textPaint != null ) {    
  253.             this.textPaint.setTextSize( this.textSize );    
  254.     public int getPaddingTop() {    
  255.         return paddingTop;    
  256.     public void setPaddingTop(int paddingTop) {    
  257.         this.paddingTop = paddingTop;    
  258.     public int getPaddingBottom() {    
  259.         return paddingBottom;    
  260.     public void setPaddingBottom(int paddingBottom) {    
  261.         this.paddingBottom = paddingBottom;    
  262.     public int getPaddingLeft() {    
  263.         return paddingLeft;    
  264.     public void setPaddingLeft(int paddingLeft) {    
  265.         this.paddingLeft = paddingLeft;    
  266.     public int getPaddingRight() {    
  267.         return paddingRight;    
  268.     public void setPaddingRight(int paddingRight) {    
  269.         this.paddingRight = paddingRight;    
  270.     public int getBarColor() {    
  271.         return barColor;    
  272.     public void setBarColor(int barColor) {    
  273.         this.barColor = barColor;    
  274.             this.barPaint.setColor( this.barColor );    
  275.     public int getCircleColor() {    
  276.         return circleColor;    
  277.     public void setCircleColor(int circleColor) {    
  278.         this.circleColor = circleColor;    
  279.         if ( this.circlePaint != null ) {    
  280.             this.circlePaint.setColor( this.circleColor);    
  281.     public int getRimColor() {    
  282.         return rimColor;    
  283.     public void setRimColor(int rimColor) {    
  284.         this.rimColor = rimColor;    
  285.         if ( this.rimPaint != null ) {    
  286.             this.rimPaint.setColor( this.rimColor );    
  287.     public Shader getRimShader() {    
  288.         return rimPaint.getShader();    
  289.     public void setRimShader(Shader shader) {    
  290.         this.rimPaint.setShader(shader);    
  291.     public int getTextColor() {    
  292.         return textColor;    
  293.     public void setTextColor(int textColor) {    
  294.         this.textColor = textColor;    
  295.             this.textPaint.setColor( this.textColor );    
  296.     public int getSpinSpeed() {    
  297.         return spinSpeed;    
  298.     public void setSpinSpeed(int spinSpeed) {    
  299.         this.spinSpeed = spinSpeed;    
  300.     public int getRimWidth() {    
  301.         return rimWidth;    
  302.     public void setRimWidth(int rimWidth) {    
  303.         this.rimWidth = rimWidth;    
  304.             this.rimPaint.setStrokeWidth( this.rimWidth );    
  305.     public int getDelayMillis() {    
  306.         return delayMillis;    
  307.     public void setDelayMillis(int delayMillis) {    
  308.         this.delayMillis = delayMillis;    
  309.     public int getContourColor() {    
  310.         return contourColor;    
  311.     public void setContourColor(int contourColor) {    
  312.         this.contourColor = contourColor;    
  313.         if ( contourPaint != null ) {    
  314.             this.contourPaint.setColor( this.contourColor );    
  315.     public float getContourSize() {    
  316.         return this.contourSize;    
  317.     public void setContourSize(float contourSize) {    
  318.         this.contourSize = contourSize;    
  319.             this.contourPaint.setStrokeWidth( this.contourSize );    
  320. }    

繼續閱讀