自定義View之—漸變進度條
最近項目中用到漸變圓環進度條,自己也寫了一下,用到一些知識,以前沒有用過,使用過程中有一些問題,在此做一下筆記。
漸變顏色其實用到的是顏色數組,然后根據數組計算來的,當然計算是Android系統進行的,不需要我們手動計算,我們只需要設置顏色數組和顏色值對應位置即可。畫圓形漸變用到一個屬性:SweepGradient,他的父類是一個Shader,
由官方文檔看到他有兩個構造函數:
SweepGradient(float cx, float cy, int color0, int color1)
SweepGradient(float cx, float cy, int colors[], float positions[])
- cx:要畫的圓環的中心點x坐標;
- cy:要畫的圓環的中心點y坐標;
- color0:起始顏色值;
- color1:結束顏色值;
- colors[]:顏色數組;
- positions[]:對應顏色值的位置,與顏色值數組個數相等,里面的值均為(0–1)的數字。
先看一張效果圖(圖一):
這就是一張漸變圓環圖,上面的箭頭和數字后面解釋。
我們主要研究第二個構造函數,顏色數組和顏色位置的使用方法。
首先看一個例子:
/**
* 圓形漸變進度條
* 相關知識:
* <p>
* Created by yuchuan on 16/9/29.
*/
public class CircleGradientProgressbar extends View {
private final static int DURATION = 3000;
private int mWidth;
private int mHeight;
private int mDiam;
private int mColorGreen;
private int mColorYellow;
private int mColorRed;
private final float mMaxProgress = 100f;
//默認進度
private int mProgress = 80;
private int mCurrentProgress = 100;
//進圖條圓環寬度
private int mProgressStrokeWidth = 10;
//進度條背景畫筆
private Paint mCirclePaint;
//進度條畫筆
private Paint mProgressPaint;
private Shader mProgressShader;
//畫圓所在的距形區域
private RectF mProgressOval;
private ValueAnimator mAnimator;
public CircleGradientProgressbar(Context context) {
this(context, null);
}
public CircleGradientProgressbar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mColorGreen = getResources().getColor(R.color.mx_circle_progressbar_green);
mColorYellow = getResources().getColor(R.color.mx_circle_progressbar_orange);
mColorRed = getResources().getColor(R.color.mx_circle_progressbar_red);
mProgressOval = new RectF();
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(Color.GRAY);
mProgressPaint = new Paint();
//設置抗鋸齒
mProgressPaint.setAntiAlias(true);
//設置筆為圓角
// mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
mProgressPaint.setStyle(Paint.Style.STROKE);
mAnimator = ValueAnimator.ofFloat(0, 1f);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float percent = (float) animation.getAnimatedValue();
if (percent > 0) {
mCurrentProgress = (int) (mProgress * percent);
postInvalidate();
}
}
});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mWidth = getWidth();
mHeight = getHeight();
mDiam = Math.min(mWidth, mHeight);
mProgressStrokeWidth = mDiam / 6;
drawCircle(canvas);
drawSweepProgressBar(canvas, mWidth / 2, mHeight / 2);
}
private void drawCircle(Canvas canvas) {
canvas.drawArc(mProgressOval, 0, 360, false, mCirclePaint);
}
/**
* 畫漸變圓環:
* colorSweep[]: 漸變顏色數組
* position[]: 每個顏色值的相對位置,個數與顏色數組個數相等
* 注:位置與漸變顏色值的設置教程見博客:
*
* @param canvas 畫布
* @param cx 圓環中心X坐標
* @param cy 圓環中心Y坐標
*/
private void drawSweepProgressBar(Canvas canvas, int cx, float cy) {
//設置圓環的大小
mProgressOval.top = cy - mDiam / 4;
mProgressOval.left = cx - mDiam / 4;
mProgressOval.bottom = cy + mDiam / 4;
mProgressOval.right = cx + mDiam / 4;
//畫漸變顏色
int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0f,0.5f,0.7f};
mProgressShader = new SweepGradient(cx, cy, colorSweep, position);
mProgressPaint.setShader(mProgressShader);
mProgressPaint.setStrokeWidth(mProgressStrokeWidth);
canvas.drawArc(mProgressOval, 0, ((float) mCurrentProgress / mMaxProgress) * 360, false, mProgressPaint); // 繪制進度圓弧,這里是藍色
}
public void setProgress(int progress) {
this.mProgress = progress;
if (mAnimator != null && progress > 0) {
if (mAnimator.isRunning()) {
return;
}
mAnimator.setDuration((long) (DURATION / mMaxProgress * progress));
mAnimator.start();
}
}
}
效果圖如下:
此時的顏色數組和位置參數為:
int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0f,0.5f,0.7f};
下面我們更改一下顏色值的位置:
int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0.25f,0.5f,0.75f};
效果圖如下:
對比上面兩個圖片我們看到隨著第一個位置的值的增大,第一個顏色值的漸變色開始位置也在向后移動。此時我們畫圓環是從0度開始的,也就是3點鐘的位置開始,順時針開始畫圓環。第一個顏色綠色也是從這個位置開始的。那么我們看看如果我改變開始畫的位置,有什么變化嗎?
我用上面第二組的數據,然后只改變畫圓環的初始位置:
int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0.25f,0.5f,0.75f};
canvas.drawArc(mProgressOval, 0, ((float) mCurrentProgress / mMaxProgress) * 360, false, mProgressPaint);
效果圖如下:
顯示效果和上面一個是一樣的,只是運行時你會發現,圓環是從(圖一)0.75那個位置開始順時針畫的,并且開始畫的顏色是紅色的,由此判斷,第一個顏色值是用(圖一)0的那個位置順時針開始計算的,那么如果我想從0.75那個位置開始畫并且顏色從綠的開始怎么畫,那你需要將開始畫的角度改為:-90,然后更改顏色數組和顏色位置數組:
int colorSweep[] = {mColorGreen, mColorGreen, mColorYellow, mColorRed, mColorGreen, mColorGreen};
float position[] = {0.1f, 0.25f, 0.5f, 0.751f, 0.75f, 1f};
canvas.drawArc(mProgressOval, -90, ((float) mCurrentProgress / mMaxProgress) * 360, false, mProgressPaint);
效果圖如下:
此時我們看到,綠色是從(圖一)0.75位置開始的,并且圓環也是從這個位置開始畫的,但是此時我的顏色值和位置增加了,主要是后面部分,倒數第二個顏色值是綠色,對應位置是0.75,也是就分段設置顏色值,0.75的位置為綠色,最后一個也是綠色,則說明從0.75之后到1的位置都是綠色,然后0后面的顏色根據位置數組第一個參數開始計算,如果角度不是0就要按照這個計算進行調整。
另外,最后一個例子中相同顏色設置了多個,這個是調節漸變和純色位置的,也就是相同顏色位置間的顏色是純色的,不同顏色值中間的顏色是過度的,自己可以調節一下掌握以下技巧。