1. 程式人生 > >Android 自定義 View 圓形進度條總結

Android 自定義 View 圓形進度條總結

Android 自定義圓形進度條總結

最近擼了一個圓形進度條的開源專案,算是第一次完完整整的使用自定義 View 。在此對專案開發思路做個小結,歡迎大家 Star 和 Fork

該專案總共實現了三種圓形進度條效果

  1. CircleProgress:圓形進度條,可以實現仿 QQ 健康計步器的效果,支援配置進度條背景色、寬度、起始角度,支援進度條漸變
  2. DialProgress:類似 CircleProgress,但是支援刻度
  3. WaveProgress:實現了水波紋效果的圓形進度條,不支援漸變和起始角度配置,如需此功能可參考 CircleProgress 自行實現。

先上效果圖,有圖才好說。
CircleProgress 效果圖
a w300

DialProgress 和 WaveProgress 效果圖
b w300

恩,那麼接下來,就來講講怎麼實現以上自定義進度條的效果。

圓形進度條

圓形進度條是第一個實現的進度條效果,用了我大半天的時間,實現起來並不複雜。

其思路主要可以分為以下幾步:

  1. View 的測量
  2. 計算繪製 View 所需引數
  3. 圓弧的繪製及漸變的實現
  4. 文字的繪製
  5. 動畫效果的實現

首先,我們要測量出所繪製 View 的大小,即重寫 onMeasure() 方法,程式碼如下:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   super
.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(MiscUtil.measure(widthMeasureSpec, mDefaultSize), MiscUtil.measure(heightMeasureSpec, mDefaultSize)); }

由於其他兩個進度條類都需要實現 View 的測量,這裡對程式碼進行了封裝:

/**
* 測量 View
*
* @param measureSpec
* @param defaultSize View 的預設大小
* @return 
測量出來的 View 大小 */ public static int measure(int measureSpec, int defaultSize) { int result = defaultSize; int specMode = View.MeasureSpec.getMode(measureSpec); int specSize = View.MeasureSpec.getSize(measureSpec); if (specMode == View.MeasureSpec.EXACTLY) { result = specSize; } else if (specMode == View.MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } return result; }

接下來,在 onSizeChanged() 中計算繪製圓及文字所需的引數,考慮到螢幕旋轉的情況,故未直接在 onMeasure() 方法中直接計算。這裡以下面草圖來講解繪製計算過程中的注意事項,圖醜,勿怪~
WechatIMG2 w300

圖中,外面藍色矩形為 View,裡面黑色矩形為圓的外接矩形,藍色矩形和黑色矩形中間空白的地方為 View 的內邊距(padding)。兩個藍色的圓其實是一個圓,代表圓的粗細,這是因為 Android 在繪製圓或者圓弧的時候是圓的邊寬的中心與外接矩形相交,所以在計算的時候要考慮到內邊距(padding) 和 圓與外接矩形的相交。

預設不考慮圓弧的寬度,繪製出來的效果如下:
device-2017-03-02-071101 w300

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   super.onSizeChanged(w, h, oldw, oldh);
   Log.d(TAG, "onSizeChanged: w = " + w + "; h = " + h + "; oldw = " + oldw + "; oldh = " + oldh);
   //求圓弧和背景圓弧的最大寬度
   float maxArcWidth = Math.max(mArcWidth, mBgArcWidth);
   //求最小值作為實際值
   int minSize = Math.min(w - getPaddingLeft() - getPaddingRight() - 2 * (int) maxArcWidth,
           h - getPaddingTop() - getPaddingBottom() - 2 * (int) maxArcWidth);
   //減去圓弧的寬度,否則會造成部分圓弧繪製在外圍
   mRadius = minSize / 2;
   //獲取圓的相關引數
   mCenterPoint.x = w / 2;
   mCenterPoint.y = h / 2;
   //繪製圓弧的邊界
   mRectF.left = mCenterPoint.x - mRadius - maxArcWidth / 2;
   mRectF.top = mCenterPoint.y - mRadius - maxArcWidth / 2;
   mRectF.right = mCenterPoint.x + mRadius + maxArcWidth / 2;
   mRectF.bottom = mCenterPoint.y + mRadius + maxArcWidth / 2;
   //計算文字繪製時的 baseline
   //由於文字的baseline、descent、ascent等屬性只與textSize和typeface有關,所以此時可以直接計算
   //若value、hint、unit由同一個畫筆繪製或者需要動態設定文字的大小,則需要在每次更新後再次計算
   mValueOffset = mCenterPoint.y - (mValuePaint.descent() + mValuePaint.ascent()) / 2;
   mHintOffset = mCenterPoint.y * 2 / 3 - (mHintPaint.descent() + mHintPaint.ascent()) / 2;
   mUnitOffset = mCenterPoint.y * 4 / 3 - (mUnitPaint.descent() + mUnitPaint.ascent()) / 2;
   updateArcPaint();
   Log.d(TAG, "onSizeChanged: 控制元件大小 = " + "(" + w + ", " + h + ")"
           + "圓心座標 = " + mCenterPoint.toString()
           + ";圓半徑 = " + mRadius
           + ";圓的外接矩形 = " + mRectF.toString());
}

關於 Android 中文字繪製可以參考以下兩篇文章:

以上,已經基本完成了 View 繪製所需全部引數的計算。接下來就是繪製圓弧及文字了。

繪製圓弧需要用到 Canvas 的

// oval 為 RectF 型別,即圓弧顯示區域
// startAngle 和 sweepAngle  均為 float 型別,分別表示圓弧起始角度和圓弧度數。3點鐘方向為0度,順時針遞增
// 如果 startAngle < 0 或者 > 360,則相當於 startAngle % 360
// useCenter:如果為 true 時,在繪製圓弧時將圓心包括在內,通常用來繪製扇形
// 繪製圓弧的畫筆
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);

為了方便計算,繪製圓弧的時候使用了 Canvas 的 rotate() 方法,對座標系進行了旋轉

private void drawArc(Canvas canvas) {
   // 繪製背景圓弧
   // 從進度圓弧結束的地方開始重新繪製,優化效能
   canvas.save();
   float currentAngle = mSweepAngle * mPercent;
   canvas.rotate(mStartAngle, mCenterPoint.x, mCenterPoint.y);
   // +2 是因為繪製的時候出現了圓弧起點有尾巴的問題
   canvas.drawArc(mRectF, currentAngle, mSweepAngle - currentAngle + 2, false, mBgArcPaint);
   canvas.drawArc(mRectF, 2, currentAngle, false, mArcPaint);
   canvas.restore();
}

恩,圓環已經繪製完成,那麼接下來就是實現圓環的漸變,這裡使用 SweepGradient 類。SweepGradient 可以實現從中心放射性漸變的效果,如下圖:
1344993412_1866

SweepGradient 類有兩個構造方法,

/**
 * @param cx 渲染中心點x座標
 * @param cy 渲染中心點y座標
 * @param colors 圍繞中心渲染的顏色陣列,至少要有兩種顏色值
 * @param positions 相對位置的顏色陣列,可為null,  若為null,可為null,顏色沿漸變線均勻分佈。一般不需要設定該引數
 /
public SweepGradient(float cx, float cy, int[] colors, float[] positions)

/**
 * @param cx 渲染中心點x座標
 * @param cy 渲染中心點y座標
 * @param color0 起始渲染顏色
 * @param color1 結束渲染顏色
 /
public SweepGradient(float cx, float cy, int color0, int color1)

這裡我們選擇第一個構造方法。由於設定漸變需要每次都建立一個新的 SweepGradient 物件,所以最好不要放到 onDraw 方法中去更新,最好在初始化的時候就設定好,避免頻繁建立導致記憶體抖動。

private void updateArcPaint() {
   // 設定漸變
   int[] mGradientColors = {Color.GREEN, Color.YELLOW, Color.RED};
   mSweepGradient = new SweepGradient(mCenterPoint.x, mCenterPoint.y, mGradientColors, null);
   mArcPaint.setShader(mSweepGradient);
}

這裡還有一個值得注意的地方,草圖如下
WechatIMG3 w300
假設,漸變顏色如下:

int[] mGradientColors = {Color.GREEN, Color.YELLOW, Color.RED, Color.BLUE};

因為 SweepGradient 漸變是 360 度的,所以如果你繪製的圓弧只有 270度,則藍色部分(圖中黑色陰影部分)的漸變就會不可見。

接下來,就是文字的繪製了。文字繪製在上述提到的文章中已經進行了詳細的講解,這裡就不再贅述。程式碼如下:

private void drawText(Canvas canvas) {
   canvas.drawText(String.format(mPrecisionFormat, mValue), mCenterPoint.x, mValueOffset, mValuePaint);

   if (mHint != null) {
       canvas.drawText(mHint.toString(), mCenterPoint.x, mHintOffset, mHintPaint);
   }

   if (mUnit != null) {
       canvas.drawText(mUnit.toString(), mCenterPoint.x, mUnitOffset, mUnitPaint);
   }
}

最後,我們來實現進度條的動畫效果。這裡我們使用 Android 的屬性動畫來實現進度更新。

private void startAnimator(float start, float end, long animTime) {
   mAnimator = ValueAnimator.ofFloat(start, end);
   mAnimator.setDuration(animTime);
   mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
       @Override
       public void onAnimationUpdate(ValueAnimator animation) {
           mPercent = (float) animation.getAnimatedValue();
           mValue = mPercent * mMaxValue;
           if (BuildConfig.DEBUG) {
               Log.d(TAG, "onAnimationUpdate: percent = " + mPercent
                       + ";currentAngle = " + (mSweepAngle * mPercent)
                       + ";value = " + mValue);
           }
           invalidate();
       }
   });
   mAnimator.start();
}

這裡有兩個注意點:

  1. 不要在 ValueAnimator.AnimatorUpdateListener 中輸出 Log,特別是動畫呼叫頻繁的情況下,因為輸出 Log 頻繁會生成大量 String 物件造成記憶體抖動,當然也可以使用 StringBuilder 來優化。
  2. 關於 invalidate()postInvalidate() 兩者最本質的前者只能在 UI 執行緒中使用,而後者可以在非 UI 執行緒中使用,其實 postInvalidate() 內部也是使用 Handler 實現的。

關於 Android 屬性動畫可以參考:

補充:同一個屬性如何支援顏色和顏色陣列

考慮到圓弧設定單色和漸變的區別,即單色只需要提供一種色值,而漸變至少需要提供兩種色值。可以有以下幾種解決方案:

  1. 定義兩個屬性,漸變的優先順序高於單色的。
  2. 定義一個 format 為 string 屬性,以 #FFFFFF|#000000 形式提供色值
  3. 定義一個 format 為 color|reference 的屬性,其中 reference 屬性指代漸變色的陣列。

這裡選用第三種方案,實現如下:

<!-- 圓形進度條 -->
<declare-styleable name="CircleProgressBar">
    <!-- 圓弧顏色, -->
    <attr name="arcColors" format="color|reference" />
</declare-styleable>

<!-- colors.xml -->
<color name="green">#00FF00</color>
<color name="blue">#EE9A00</color>
<color name="red">#EE0000</color>
<!-- 漸變顏色陣列 -->
<integer-array name="gradient_arc_color">
   <item>@color/green</item>
   <item>@color/blue</item>
   <item>@color/red</item>
</integer-array>

<!-- 佈局檔案中使用 -->
<!-- 使用漸變 -->
<com.littlejie.circleprogress.DialProgress
    android:id="@+id/dial_progress_bar"
    android:layout_width="300dp"
    android:layout_height="300dp"
    app:arcColors="@array/gradient_arc_color" />
<!-- 使用單色 -->    
<com.littlejie.circleprogress.DialProgress
    android:id="@+id/dial_progress_bar"
    android:layout_width="300dp"
    android:layout_height="300dp"
    app:arcColors="@color/green" />

程式碼中讀取 xml 中配置:

int gradientArcColors = typedArray.getResourceId(R.styleable.CircleProgressBar_arcColors, 0);
   if (gradientArcColors != 0) {
       try {
           int[] gradientColors = getResources().getIntArray(gradientArcColors);
           if (gradientColors.length == 0) {//如果漸變色為陣列為0,則嘗試以單色讀取色值
               int color = getResources().getColor(gradientArcColors);
               mGradientColors = new int[2];
               mGradientColors[0] = color;
               mGradientColors[1] = color;
           } else if (gradientColors.length == 1) {//如果漸變陣列只有一種顏色,預設設為兩種相同顏色
               mGradientColors = new int[2];
               mGradientColors[0] = gradientColors[0];
               mGradientColors[1] = gradientColors[0];
           } else {
               mGradientColors = gradientColors;
           }
       } catch (Resources.NotFoundException e) {
           throw new Resources.NotFoundException("the give resource not found.");
       }
   }

帶刻度進度條

前面,詳細講了 CircleProgress 的繪製思路,接下來講 DialProgress。

實話說,DialProgress 與 CircleProgress 的實現極其相似,因為兩者之間其實就差了一個刻度,但考慮到擴充套件以及類職責的單一,所以將兩者分開。

這裡主要講一下刻度的繪製。刻度繪製主要使用 Canvas 類的 save()rotate()restore() 方法,當然你也可以使用 translate() 方法對座標系進行平移,方便計算。

/**
 * 用來儲存Canvas的狀態。save之後,可以呼叫Canvas的平移、放縮、旋轉、錯切、裁剪等操作。
 */
public void save()

/**
 * 旋轉一定的角度繪製圖像
 * @param degrees 旋轉角度
 * @param x 旋轉中心點x軸座標
 * @param y 旋轉中心點y軸座標
 */
public void rotate(float degrees, float x, float y)

/**
 * 在當前的座標上平移(x,y)個畫素單位
 * 若dx <0 ,沿x軸向上平移; dx >0  沿x軸向下平移
 * 若dy <0 ,沿y軸向上平移; dy >0  沿y軸向下平移
 */
public void translate(float dx, float dy)

/**
 * 用來恢復Canvas之前儲存的狀態。防止save後對Canvas執行的操作對後續的繪製有影響。
 */
public void restore()
private void drawDial(Canvas canvas) {
   int total = (int) (mSweepAngle / mDialIntervalDegree);
   canvas.save();
   canvas.rotate(mStartAngle, mCenterPoint.x, mCenterPoint.y);
   for (int i = 0; i <= total; i++) {
       canvas.drawLine(mCenterPoint.x + mRadius, mCenterPoint.y, mCenterPoint.x + mRadius + mArcWidth, mCenterPoint.y, mDialPaint);
       canvas.rotate(mDialIntervalDegree, mCenterPoint.x, mCenterPoint.y);
   }
   canvas.restore();
}

水波紋效果的進度條

水波紋效果的進度條實現需要用到貝塞爾曲線,主要難點在於 繪製區域的計算波浪效果 的實現,其餘的邏輯跟上述兩種進度條相似。

這裡使用了 Path 類,該類在 Android 2D 繪圖中是非常重要的,Path 不僅能夠繪製簡單圖形,也可以繪製這些比較複雜的圖形。也可以對多個路徑進行布林操作,類似設定 Paint 的 setXfermode() ,具體使用可以參考這篇部落格:安卓自定義View進階-Path基本操作。這裡就不再贅述,有機會自己也會對 Android 自定義 View 的知識進行總結,不過,感覺應該了了無期。

繼續上示意圖,請叫我靈魂畫手~
WechatIMG1

圖中黑色的圓為我們要繪製的進度條圓,黑色的曲線為初始狀態的的波浪,該波浪使用貝塞爾曲線繪製,其中奇數的點為貝塞爾曲線的起始點,偶數的點為貝塞爾曲線的控制點。例如:1——>2——>3就為一條貝塞爾曲線,1 是起點,2 是控制點,3 是終點。從圖中可以看到波浪在園內圓外各一個(1—>5 和 5->9),通過對波浪在 x 軸上做平移,即圖中藍色實線,來實現波浪的動態效果,所以一個波浪的完整動畫效果需要有兩個波浪來實現。同理,通過控制 y 軸的偏移量,即圖中藍色虛線,可以實現波浪隨進度的上漲下降。

貝塞爾曲線上起始點和控制點的計算如下:

/**
 * 計算貝塞爾曲線上的起始點和控制點
 * @param waveWidth 一個完整波浪的寬度
 */
private Point[] getPoint(float waveWidth) {
   Point[] points = new Point[mAllPointCount];
   //第1個點特殊處理,即陣列的中心
   points[mHalfPointCount] = new Point((int) (mCenterPoint.x - mRadius), mCenterPoint.y);
   //螢幕內的貝塞爾曲線點
   for (int i = mHalfPointCount + 1; i < mAllPointCount; i += 4) {
       float width = points[mHalfPointCount].x + waveWidth * (i / 4 - mWaveNum);
       points[i] = new Point((int) (waveWidth / 4 + width), (int) (mCenterPoint.y - mWaveHeight));
       points[i + 1] = new Point((int) (waveWidth / 2 + width), mCenterPoint.y);
       points[i + 2] = new Point((int) (waveWidth * 3 / 4 + width), (int) (mCenterPoint.y + mWaveHeight));
       points[i + 3] = new Point((int) (waveWidth + width), mCenterPoint.y);
   }
   //螢幕外的貝塞爾曲線點
   for (int i = 0; i < mHalfPointCount; i++) {
       int reverse = mAllPointCount - i - 1;
       points[i] = new Point(points[mHalfPointCount].x - points[reverse].x,
               points[mHalfPointCount].y * 2 - points[reverse].y);
   }
   return points;
}

以上,我們已經獲取到繪製貝塞爾曲線所需的路徑點。接下來,我們就需要來計算出繪製區域,即使用 Path 類。

WechatIMG1

紫色區域為貝塞爾曲線需要繪製的整體區域。

WechatIMG1
紅色區域為上圖紫色區域與圓的交集,也就是波浪要顯示的區域

程式碼如下:

//該方法必須在 Android 19以上的版本才能使用(Path.op())
@TargetApi(Build.VERSION_CODES.KITKAT)
private void drawWave(Canvas canvas, Paint paint, Point[] points, float waveOffset) {
   mWaveLimitPath.reset();
   mWavePath.reset();
   //lockWave 用於判斷波浪是否隨進度條上漲下降
   float height = lockWave ? 0 : mRadius - 2 * mRadius * mPercent;
   //moveTo和lineTo繪製出水波區域矩形
   mWavePath.moveTo(points[0].x + waveOffset, points[0].y + height);

   for (int i = 1; i < mAllPointCount; i += 2) {
       mWavePath.quadTo(points[i].x + waveOffset, points[i].y + height,
               points[i + 1].x + waveOffset, points[i + 1].y + height);
   }
   mWavePath.lineTo(points[mAllPointCount - 1].x, points[mAllPointCount - 1].y + height);
   //不管如何移動,波浪與圓路徑的交集底部永遠固定,否則會造成上移的時候底部為空的情況
   mWavePath.lineTo(points[mAllPointCount - 1].x, mCenterPoint.y + mRadius);
   mWavePath.lineTo(points[0].x, mCenterPoint.y + mRadius);
   mWavePath.close();
   mWaveLimitPath.addCircle(mCenterPoint.x, mCenterPoint.y, mRadius, Path.Direction.CW);
   //取該圓與波浪路徑的交集,形成波浪在圓內的效果
   mWaveLimitPath.op(mWavePath, Path.Op.INTERSECT);
   canvas.drawPath(mWaveLimitPath, paint);
}

以上,就實現了水波動態的效果,當然,你也可以通過配置,來設定水波是否隨進度上漲下降。為了實現更好的效果,可以設定一個淺色的水波並支援設定水波的走向(R2L 和 L2R),通過設定淺色波浪和深色波浪動畫的時間,從而實現長江後浪推前浪的效果,恩,效果很自然的~自己腦補從右至左波浪的實現和貝塞爾點的計算。

對獲取座標點的程式碼進行優化:

/**
* 從左往右或者從右往左獲取貝塞爾點
*
* @return
*/
private Point[] getPoint(boolean isR2L, float waveWidth) {
   Point[] points = new Point[mAllPointCount];
   //第1個點特殊處理,即陣列的中點
   points[mHalfPointCount] = new Point((int) (mCenterPoint.x + (isR2L ? mRadius : -mRadius)), mCenterPoint.y);
   //螢幕內的貝塞爾曲線點
   for (int i = mHalfPointCount + 1; i < mAllPointCount; i += 4) {
       float width = points[mHalfPointCount].x + waveWidth * (i / 4 - mWaveNum);
       points[i] = new Point((int) (waveWidth / 4 + width), (int) (mCenterPoint.y - mWaveHeight));
       points[i + 1] = new Point((int) (waveWidth / 2 + width), mCenterPoint.y);
       points[i + 2] = new Point((int) (waveWidth * 3 / 4 + width), (int) (mCenterPoint.y + mWaveHeight));
       points[i + 3] = new Point((int) (waveWidth + width), mCenterPoint.y);
   }
   //螢幕外的貝塞爾曲線點
   for (int i = 0; i < mHalfPointCount; i++) {
       int reverse = mAllPointCount - i - 1;
       points[i] = new Point((isR2L ? 2 : 1) * points[mHalfPointCount].x - points[reverse].x,
               points[mHalfPointCount].y * 2 - points[reverse].y);
   }
   //對從右向左的貝塞爾點陣列反序,方便後續處理
   return isR2L ? MiscUtil.reverse(points) : points;
}

至此,自定義圓形進度條相關的思路已全部講述完成。程式碼已全部上傳至 Git ,歡迎大家 Star 和 Fork,傳送門:CircleProgress

如有不清楚或者錯誤的地方,歡迎指出~

相關推薦

Android 定義 View 圓形進度總結

Android 自定義圓形進度條總結 最近擼了一個圓形進度條的開源專案,算是第一次完完整整的使用自定義 View 。在此對專案開發思路做個小結,歡迎大家 Star 和 Fork 該專案總共實現了三種圓形進度條效果 CircleProgress:圓形進度條,可以實現仿 QQ

Android定義View-圓形進度

好幾天不寫部落格了,這段時間一直沒時間,感覺一直在忙,但是進度不大。 好了,言歸正傳,最近專案裡要用到這麼一個自定義view,是一個圓形的進度圓環,現在學習下怎麼來自定義它。 原始碼下載地址 自定義之前先分析一下,這個自定義View主要有以下幾

Android定義View--圓形進度RoundProgress

要實現的效果 需要知道的知識點 字型的高度和寬度是怎麼測? 字型的高度就是textSize的大小。 字型的寬度怎麼測量呢?Paint畫筆中有測量字型寬度的api,如下: //測量字型的寬度 float width =

Android 定義View -- 圓形進度,文字旋轉

最近公司招聘打個廣告: 公司屬於外企福利待遇好, 每週英語課, 關鍵時單身妹子多[色][色] 詳情 [點選全棧JavaScript工程師] Android 自定義View – 圓形進度條,文字旋轉 作為一名

Android定義View——圓形進度式按鈕

介紹 今天上班的時候有個哥們問我怎麼去實現一個按鈕式的進度條,先來看看他需要實現的效果圖。 和普通的圓形進度條類似,只是中間的地方有兩個狀態表示,未開始,暫停狀態。而且他說圓形進度的功能已經實現了。那麼我們只需要對中間的兩個狀態做處理就行了。 先來看看

定義View圓形進度 跳轉頁面

效果展示 1.匯入依賴 implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 2.建立自定義Vie

Android定義View——投票進度

效果展示 功能屬性介紹 <!-- MatchSupportProgressBar --> <declare-styleable

定義view圓形進度,矩形與二維碼

主介面佈局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width

定義View圓形進度帶跳轉頁面

MainActivity: public class MainActivity extends AppCompatActivity { private Button btnAdd; private ProgressView pv;

Android 定義view --圓形百分比(進度

注:本文由於是在學習過程中寫的,存在大量問題(overdraw onDraw new物件),請讀者們不要被誤導!!解決辦法見後面的部落格。 起因 最近公司專案有需求需要用到輕量級圖表如下

Android 定義View 圓形百分比進度

Android 自定義View  圓形百分比進度條 自定義View package com.arch.circleprogressview; import android.content.Context; import android.graphics.Canvas;

android定義的弧形進度圓形進度-SemicircleProgress

SemicircleProgress 兩個自定義圓形和弧形進度條 第一個SemicircleProgress可以對中間和下面的字自定義 第二個CircularProgressar可

定義View載入進度首頁面

1.主頁面佈局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:

android定義ProgressBar 修改進度樣式 出現setProgress無效問題

在很多時候android系統提供的進度條樣式是不足以滿足我們的需求的,因此在大多數的時候,我們為了美觀,亦或者為了實現自己的功能,需要在系統的基礎上進行修改其樣式,當然你也可以自己從頭寫一個,不過個人覺得還是比較麻煩,好吧,廢話不多說了,進入正題。 昨天在做一個下載功能時,

定義Qt圓形進度

主要程式碼: #include "diaplot.h" #include "qpainter.h" #include "qdebug.h" DialPlot::DialPlot(QWidget *parent) : QWidget(parent) {

android 定義view 圓形可移動

Mycircle2 extends View { private Paint paint; private int rawX; private int rawY; private int wid; private int he; int statusBarHe

android定義notification實現進度功能

要建立一個自定義的Notification,可以使用RemoteViews。要定義自己的擴充套件訊息,首先要初始化一個RemoteViews物件,然後將它傳遞給Notification contentView欄位,再把PendingIntent傳遞給contentIntent

Android定義view-繪製圓形進度

詳細可參考:http://blog.csdn.net/Beyond0525/article/details/48181345最近專案上有一些需求,需要繪製圓形的進度條滿足設計上和互動上的需求: 實現思路在畫布上直接繪製View,需要了解一下幾點 1.需要畫一個圓 2.圓圈上有

Android定義View——從零開始實現圓形進度

前言:以前老是用別人造的輪子,知其然不知其所以然,有時看懂了別人寫的過多幾個月又忘了,遂來開個坑把一步步實現和思路寫下來,弄成一個系列。由於上班時間不多,爭取一週擼個一到兩篇出來 本篇只著重於思路和實現步驟,裡面用到的一些知識原理不會非常細地拿來講,如

Android 定義View之仿華為圓形載入進度

效果圖 實現思路 可以看出該View可分為三個部分來實現 最外圍的圓,該部分需要區分進度圓和底部的刻度圓,進度部分的刻度需要和底色刻度區分開來 中間顯示的文字進度,需要讓文字在View中居中顯示 旋轉的小圓點,小圓點需要模擬小球下落運動時的加速度