Android中圓形進度條的應用還是挺多的,最近學習實現(xiàn)了圓形進度條。

RingProgressBar

meizu style
思路
要實現(xiàn)圓形進度條,
首先要畫灰色背景圓環(huán)
再畫藍色進度圓環(huán)
再畫進度數(shù)字
搞定。
首先自定義各種屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RingProgressBar">
<attr name="ringColor" format="color" />
<attr name="ringProgressColor" format="color" />
<attr name="textColor" format="color" />
<attr name="ringWidth" format="dimension" />
<attr name="textSize" format="dimension" />
<attr name="max" format="integer" />
<attr name="showTextProgress" format="boolean" />
<attr name="style">
<enum name="STROKE" value="0" />
<enum name="FULL" value="1" />
</attr>
</declare-styleable>
</resources>
初始化各種屬性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
ringColor = typedArray.getColor(R.styleable.RingProgressBar_ringColor, Color.GRAY);
ringProgressColor = typedArray.getColor(R.styleable.RingProgressBar_ringProgressColor, Color.GREEN);
textColor = typedArray.getColor(R.styleable.RingProgressBar_textColor, Color.GREEN);
textSize = typedArray.getDimension(R.styleable.RingProgressBar_textSize, 16);
ringWidth = typedArray.getDimension(R.styleable.RingProgressBar_ringWidth, 5);
max = typedArray.getInteger(R.styleable.RingProgressBar_max, 100);
textIsDisplayable = typedArray.getBoolean(R.styleable.RingProgressBar_showTextProgress, true);
style = typedArray.getInt(R.styleable.RingProgressBar_style, 0);
//資源回收
typedArray.recycle();
初始化三種畫筆
//背景圓環(huán)畫筆
ringPaint = new Paint();
ringPaint.setColor(ringColor);
ringPaint.setStyle(Paint.Style.STROKE);
ringPaint.setStrokeWidth(ringWidth);
ringPaint.setAntiAlias(true);
//進度圓環(huán)畫筆
ringProgressPaint = new Paint();
ringProgressPaint.setColor(ringProgressColor);
ringProgressPaint.setStrokeWidth(ringWidth);
ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
ringProgressPaint.setAntiAlias(true);
switch (style) {
case STROKE:
ringProgressPaint.setStyle(Paint.Style.STROKE);
break;
case FULL:
ringProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
break;
}
//進度文字畫筆
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
抗鋸齒
ringPaint.setAntiAlias(true);
圓形線條
ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
圓環(huán)整體圖

圓環(huán)整體圖
畫背景圓環(huán)
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int) (xCenter - ringWidth / 2);
canvas.drawCircle(xCenter, yCenter, radius, ringPaint);
xCenter:圓心橫坐標
yCenter:圓心縱坐標
radius:半徑
ringPaint:畫筆
疑惑
這里我有點疑惑,為什么半徑是xCenter - ringWidth / 2呢?
我認為半徑應該是xCenter - ringWidth才對,很合理,寬度的一半減去線條寬度,剛好是圓環(huán)的半徑。
懷著疑惑的心情畫了上圖,這里減去圓環(huán)線條寬度的一半或許是因為線條的寬度不可忽略,姑且這樣認為吧,如果有大神看到希望指點迷津。
畫進度圓環(huán)
RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
switch (style) {
case STROKE:
/*canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);*/
canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
break;
case FULL:
if (progress != 0) {
canvas.drawArc(rectF, -90, progress * 360 / 100, true, ringProgressPaint);
}
break;
}
左上右下
RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
xCenter - radius:矩形距離左邊的距離
yCenter - radius:矩形距離上邊的距離
xCenter + radius:矩形距離右邊的距離
yCenter + radius:矩形距離下邊的距離
其實可以理解為矩形左上角的坐標和右下角的坐標
畫圓弧
canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
rectF:圓弧在這個矩形中繪制
-90:圓弧順時針繪制的開始角度
progress * 360 / max:圓弧繪制的角度
false:繪制時是否經(jīng)過圓心,當style設置為STROKE時,是沒有效果的,這里借用兩張圖片,簡單明了
當style設置為FULL,這里設置為false時

false
當style設置為FULL,這里設置為true時

true
ringProgressPaint:畫筆
魅族應用市場下載效果

meizu
canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);
將進度分兩次繪制,從底部同時向上繪制進度的一半,就達到了這個效果。
畫進度數(shù)字
String text = progress + "%";
float textWidth = textPaint.measureText(text, 0, text.length());
if (showTextProgress && progress != 0 && style == STROKE) {
canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint);
}
RingProgressBar
package com.goldou.ringprogressbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by Administrator on 2017.10.30 0030.
*/
public class RingProgressBar extends View {
private Paint ringPaint;
private Paint ringProgressPaint;
private Paint textPaint;
private int ringColor;
private int ringProgressColor;
private int textColor;
private float textSize;
private float ringWidth;
private int max;
private int progress;
private boolean showTextProgress;
private int style;
private final int STROKE = 0;
private final int FULL = 1;
private Context context;
public RingProgressBar(Context context) {
this(context, null);
}
public RingProgressBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RingProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initAttrs(context, attrs);
initPaint();
}
private void initPaint() {
ringPaint = new Paint();
ringPaint.setColor(ringColor);
ringPaint.setStyle(Paint.Style.STROKE);
ringPaint.setStrokeWidth(ringWidth);
ringPaint.setAntiAlias(true);
ringProgressPaint = new Paint();
ringProgressPaint.setColor(ringProgressColor);
ringProgressPaint.setStrokeWidth(ringWidth);
ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
ringProgressPaint.setAntiAlias(true);
switch (style) {
case STROKE:
ringProgressPaint.setStyle(Paint.Style.STROKE);
break;
case FULL:
ringProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
break;
}
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
ringColor = typedArray.getColor(R.styleable.RingProgressBar_ringColor, Color.GRAY);
ringProgressColor = typedArray.getColor(R.styleable.RingProgressBar_ringProgressColor, Color.GREEN);
textColor = typedArray.getColor(R.styleable.RingProgressBar_textColor, Color.GREEN);
textSize = typedArray.getDimension(R.styleable.RingProgressBar_textSize, 16);
ringWidth = typedArray.getDimension(R.styleable.RingProgressBar_ringWidth, 5);
max = typedArray.getInteger(R.styleable.RingProgressBar_max, 100);
showTextProgress = typedArray.getBoolean(R.styleable.RingProgressBar_showTextProgress, true);
style = typedArray.getInt(R.styleable.RingProgressBar_style, 0);
//資源回收
typedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int) (xCenter - ringWidth / 2);
canvas.drawCircle(xCenter, yCenter, radius, ringPaint);
RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
switch (style) {
case STROKE:
/*canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);*/
canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
break;
case FULL:
if (progress != 0) {
canvas.drawArc(rectF, -90, progress * 360 / 100, true, ringProgressPaint);
}
break;
}
String text = progress + "%";
float textWidth = textPaint.measureText(text, 0, text.length());
if (showTextProgress && progress != 0 && style == STROKE) {
canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint);
}
}
public synchronized int getMax() {
return max;
}
public synchronized void setMax(int max) {
if (max < 0) {
throw new IllegalArgumentException("max not less than 0");
}
this.max = max;
}
public synchronized int getProgress() {
return progress;
}
public synchronized void setProgress(int progress) {
if (progress < 0) {
throw new IllegalArgumentException("progress not less than 0");
}
if (progress > max) {
progress = max;
}
if (progress <= max) {
this.progress = progress;
postInvalidate();
}
}
public int getRingColor() {
return ringColor;
}
public void setRingColor(int ringColor) {
this.ringColor = ringColor;
}
public int getRingProgressColor() {
return ringProgressColor;
}
public void setRingProgressColor(int ringProgressColor) {
this.ringProgressColor = ringProgressColor;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
public float getRingWidth() {
return ringWidth;
}
public void setRingWidth(float roundWidth) {
this.ringWidth = roundWidth;
}
}
最后
有什么解釋不對還望各位大神指正