前幾天在群里面有人找圓形可顏色漸變進度條,其中主要的知識點是SweepGradient;
mSweepGradient = new SweepGradient(240, 360, new int[] {
Color.CYAN,
Color.DKGRAY,
Color.GRAY,
Color.LTGRAY,
Color.MAGENTA, Color.GREEN,
Color.TRANSPARENT,
Color.BLUE },
null);
如上:第三個參數為漸變顏色內容,前兩個是坐標信息,240:渲染中心點x 坐標;360:渲染中心y 點坐標。
先繪制圓形:
package com.soyoungboy.sweepgradientprogress; import android.content.Context; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.EmbossMaskFilter; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * 圓形顏色漸變的進度條 * @author soyoungboy * */ public class SweepGradientCircleProgressBar extends View { private Paint pathPaint; private Paint fillArcPaint; // 設置光源的方向 private float[] direction = new float[] {1, 1, 1}; // 設置環境光亮度 private float light = 0.4f; // 選擇要應用的反射等級 private float specular = 6; private EmbossMaskFilter emboss; private RectF oval ; private BlurMaskFilter mBlur; // view重繪的標記 private boolean reset = false; // 向 mask應用一定級別的模糊 private float blur = 3.5f; private int arcradus = 30; public SweepGradientCircleProgressBar(Context context ,AttributeSet attrs) { super(context,attrs); initPaint(); oval = new RectF(); emboss = new EmbossMaskFilter(direction, light, specular, blur); mBlur = new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL); } //初始化畫筆操作 private void initPaint() { //初始化畫筆操作 pathPaint = new Paint(); // 設置是否抗鋸齒 pathPaint.setAntiAlias(true); // 幫助消除鋸齒 pathPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 pathPaint.setStyle(Paint.Style.STROKE); pathPaint.setDither(true); pathPaint.setStrokeJoin(Paint.Join.ROUND); fillArcPaint = new Paint(); // 設置是否抗鋸齒 fillArcPaint.setAntiAlias(true); // 幫助消除鋸齒 fillArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 fillArcPaint.setStyle(Paint.Style.STROKE); fillArcPaint.setDither(true); fillArcPaint.setStrokeJoin(Paint.Join.ROUND); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int height = getMeasuredWidth(); int width = getMeasuredWidth(); //半徑 = 寬/2-圓環的寬度 int radius = width/2-arcradus; int cx = width/2; int cy = height/2; //繪制畫筆顏色 pathPaint.setColor(Color.RED); //畫筆的寬度 pathPaint.setStrokeWidth(10); pathPaint.setMaskFilter(emboss); canvas.drawCircle(cx, cy, radius, pathPaint); } }
效果如下:
在上面基礎上,繪制大圓和小圓:
package com.soyoungboy.sweepgradientprogress; import android.content.Context; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.EmbossMaskFilter; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * 圓形顏色漸變的進度條 * @author soyoungboy * */ public class SweepGradientCircleProgressBar extends View { private Paint pathPaint; private Paint fillArcPaint; // 設置光源的方向 private float[] direction = new float[] {1, 1, 1}; // 設置環境光亮度 private float light = 0.4f; // 選擇要應用的反射等級 private float specular = 6; private EmbossMaskFilter emboss; private RectF oval ; private BlurMaskFilter mBlur; // view重繪的標記 private boolean reset = false; // 向 mask應用一定級別的模糊 private float blur = 3.5f; private int arcradus = 30; public SweepGradientCircleProgressBar(Context context ,AttributeSet attrs) { super(context,attrs); initPaint(); oval = new RectF(); emboss = new EmbossMaskFilter(direction, light, specular, blur); mBlur = new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL); } //初始化畫筆操作 private void initPaint() { //初始化畫筆操作 pathPaint = new Paint(); // 設置是否抗鋸齒 pathPaint.setAntiAlias(true); // 幫助消除鋸齒 pathPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 pathPaint.setStyle(Paint.Style.STROKE); pathPaint.setDither(true); pathPaint.setStrokeJoin(Paint.Join.ROUND); fillArcPaint = new Paint(); // 設置是否抗鋸齒 fillArcPaint.setAntiAlias(true); // 幫助消除鋸齒 fillArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 fillArcPaint.setStyle(Paint.Style.STROKE); fillArcPaint.setDither(true); fillArcPaint.setStrokeJoin(Paint.Join.ROUND); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (reset) { canvas.drawColor(Color.TRANSPARENT); reset = false; } drawcircle(canvas); } private void drawcircle(Canvas canvas) { int height = getMeasuredWidth(); int width = getMeasuredWidth(); //半徑 = 寬/2-圓環的寬度 int radius = width/2-arcradus; int cx = width/2; int cy = height/2; //繪制畫筆顏色 pathPaint.setColor(Color.RED); //畫筆的寬度 pathPaint.setStrokeWidth(1); pathPaint.setMaskFilter(emboss); canvas.drawCircle(cx, cy, radius, pathPaint); pathPaint.setColor(Color.BLUE); //繪制大圓 canvas.drawCircle(width / 2, height / 2, radius + arcradus / 2 + 0.5f, pathPaint); //繪制小圓 canvas.drawCircle(width / 2, height / 2, radius - arcradus / 2 - 0.5f, pathPaint); } }
效果:
去掉繪制中間圓,並不會圓弧:
package com.soyoungboy.sweepgradientprogress; import android.content.Context; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.EmbossMaskFilter; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.SweepGradient; import android.util.AttributeSet; import android.view.View; /** * 圓形顏色漸變的進度條 * @author soyoungboy * */ public class SweepGradientCircleProgressBar extends View { private Paint pathPaint; private Paint fillArcPaint; // 設置光源的方向 private float[] direction = new float[] {1, 1, 1}; // 設置環境光亮度 private float light = 0.4f; //漸變數組 private int[] arcColors = new int[] {Colors.RED,Colors.RED_TRANSLUCENT }; // 選擇要應用的反射等級 private float specular = 6; private EmbossMaskFilter emboss; private RectF oval ; private BlurMaskFilter mBlur; // view重繪的標記 private boolean reset = false; // 向 mask應用一定級別的模糊 private float blur = 3.5f; private int arcradus = 30; public SweepGradientCircleProgressBar(Context context ,AttributeSet attrs) { super(context,attrs); initPaint(); oval = new RectF(); emboss = new EmbossMaskFilter(direction, light, specular, blur); mBlur = new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL); } //初始化畫筆操作 private void initPaint() { //初始化畫筆操作 pathPaint = new Paint(); // 設置是否抗鋸齒 pathPaint.setAntiAlias(true); // 幫助消除鋸齒 pathPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 pathPaint.setStyle(Paint.Style.STROKE); pathPaint.setDither(true); pathPaint.setStrokeJoin(Paint.Join.ROUND); fillArcPaint = new Paint(); // 設置是否抗鋸齒 fillArcPaint.setAntiAlias(true); // 幫助消除鋸齒 fillArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 fillArcPaint.setStyle(Paint.Style.STROKE); fillArcPaint.setDither(true); fillArcPaint.setStrokeJoin(Paint.Join.ROUND); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (reset) { canvas.drawColor(Color.TRANSPARENT); reset = false; } drawcircle(canvas); } private void drawcircle(Canvas canvas) { int height = getMeasuredWidth(); int width = getMeasuredWidth(); //半徑 = 寬/2-圓環的寬度 int radius = width/2-arcradus; int cx = width/2; int cy = height/2; pathPaint.setColor(Color.BLUE); //繪制大圓 canvas.drawCircle(width / 2, height / 2, radius + arcradus / 2 + 0.5f, pathPaint); //繪制小圓 canvas.drawCircle(width / 2, height / 2, radius - arcradus / 2 - 0.5f, pathPaint); // 環形顏色填充 SweepGradient sweepGradient = new SweepGradient(width / 2, height / 2, arcColors, null); fillArcPaint.setShader(sweepGradient); // 設置畫筆為白色 // 模糊效果 fillArcPaint.setMaskFilter(mBlur); // 設置線的類型,邊是圓的 fillArcPaint.setStrokeCap(Paint.Cap.ROUND); //設置圓弧的寬度 fillArcPaint.setStrokeWidth(arcradus+1); // 確定圓弧的繪制位置,也就是里面圓弧坐標和外面圓弧坐標 oval.set(width / 2 - radius, height / 2 - radius, width / 2 + radius, height / 2 + radius); // 畫圓弧,第二個參數為:起始角度,第三個為跨的角度,第四個為true的時候是實心,false的時候為空心 canvas.drawArc(oval, 0, ((float)300 /360 ) * 360, false, fillArcPaint); } }
效果如下:
尼瑪,丑爆了。
控制進度的顯示,主要是progress和max之間的配合,通過外部設置progress進度來控制進度條的動態:
上面代碼修改成如下:
package com.soyoungboy.sweepgradientprogress; import android.content.Context; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.EmbossMaskFilter; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.SweepGradient; import android.util.AttributeSet; import android.view.View; /** * 圓形顏色漸變的進度條 * @author soyoungboy * */ public class SweepGradientCircleProgressBar extends View { private Paint pathPaint; private Paint fillArcPaint; // 設置光源的方向 private float[] direction = new float[] {1, 1, 1}; // 設置環境光亮度 private float light = 0.4f; //漸變數組 private int[] arcColors = new int[] {Colors.RED,Colors.RED_TRANSLUCENT }; // 選擇要應用的反射等級 private float specular = 6; private EmbossMaskFilter emboss; private RectF oval ; private BlurMaskFilter mBlur; // view重繪的標記 private boolean reset = false; // 向 mask應用一定級別的模糊 private float blur = 3.5f; private int arcradus = 30; //初始化進度 private int progress = 0; //設置進度最大值 private int max = 100; public SweepGradientCircleProgressBar(Context context ,AttributeSet attrs) { super(context,attrs); initPaint(); oval = new RectF(); emboss = new EmbossMaskFilter(direction, light, specular, blur); mBlur = new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL); } //初始化畫筆操作 private void initPaint() { //初始化畫筆操作 pathPaint = new Paint(); // 設置是否抗鋸齒 pathPaint.setAntiAlias(true); // 幫助消除鋸齒 pathPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 pathPaint.setStyle(Paint.Style.STROKE); pathPaint.setDither(true); pathPaint.setStrokeJoin(Paint.Join.ROUND); fillArcPaint = new Paint(); // 設置是否抗鋸齒 fillArcPaint.setAntiAlias(true); // 幫助消除鋸齒 fillArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG); // 設置中空的樣式 fillArcPaint.setStyle(Paint.Style.STROKE); fillArcPaint.setDither(true); fillArcPaint.setStrokeJoin(Paint.Join.ROUND); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (reset) { canvas.drawColor(Color.TRANSPARENT); reset = false; } drawcircle(canvas); } private void drawcircle(Canvas canvas) { int height = getMeasuredWidth(); int width = getMeasuredWidth(); //半徑 = 寬/2-圓環的寬度 int radius = width/2-arcradus; int cx = width/2; int cy = height/2; pathPaint.setColor(Color.BLUE); //繪制大圓 canvas.drawCircle(width / 2, height / 2, radius + arcradus / 2 + 0.5f, pathPaint); //繪制小圓 canvas.drawCircle(width / 2, height / 2, radius - arcradus / 2 - 0.5f, pathPaint); // 環形顏色填充 SweepGradient sweepGradient = new SweepGradient(width / 2, height / 2, arcColors, null); fillArcPaint.setShader(sweepGradient); // 設置畫筆為白色 // 模糊效果 fillArcPaint.setMaskFilter(mBlur); // 設置線的類型,邊是圓的 fillArcPaint.setStrokeCap(Paint.Cap.ROUND); //設置圓弧的寬度 fillArcPaint.setStrokeWidth(arcradus+1); // 確定圓弧的繪制位置,也就是里面圓弧坐標和外面圓弧坐標 oval.set(width / 2 - radius, height / 2 - radius, width / 2 + radius, height / 2 + radius); // 畫圓弧,第二個參數為:起始角度,第三個為跨的角度,第四個為true的時候是實心,false的時候為空心 canvas.drawArc(oval, 0, ((float)progress /max ) * 360, false, fillArcPaint); } public int getProgress() { return progress; } public void setProgress(int progress) { this.progress = progress; this.invalidate(); } public int getMax() { return max; } public void setMax(int max) { this.max = max; } /** * 描述:重置進度 * * @throws */ public void reset() { reset = true; this.progress = 0; this.invalidate(); } }
activity代碼:
package com.soyoungboy.sweepgradientprogress; import android.os.Bundle; import android.os.Handler; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener{ private SweepGradientCircleProgressBar progress; private Button resetBtn; // 最大100 private int max = 100; private int myProgress = 0; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case 1: startAddProgress(); break; default: break; } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progress = (SweepGradientCircleProgressBar) findViewById(R.id.progress); resetBtn = (Button) findViewById(R.id.resetBtn); resetBtn.setOnClickListener(this); startAddProgress(); } private void startAddProgress() { myProgress = myProgress + 10; progress.setProgress(myProgress); handler.sendEmptyMessageDelayed(1, 1000); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.resetBtn: //重置操作 myProgress = 0; progress.reset(); break; default: break; } } }
效果如下:
增加控制顏色的代碼:
public int[] getArcColors() { return arcColors; } public void setArcColors(int[] arcColors) { this.arcColors = arcColors; }
activity中使用:
private void startAddProgress() { myProgress = myProgress + 10; progress.setProgress(myProgress); int[] arcColors = new int[]{ Color.parseColor("#99cccc"), Color.parseColor("#ccffff"), Color.parseColor("#ffcccc"), Color.parseColor("#6699cc"), Color.parseColor("#99ccff"), Color.parseColor("#6699cc"), Color.parseColor("#cc6699"), Color.parseColor("#ffff00") }; progress.setArcColors(arcColors ); handler.sendEmptyMessageDelayed(1, 1000); }
效果如下:
為了不至於開頭那段顏色那么突兀,也就是丑,可以修改代碼中顏色數組,將顏色數組第一個顏色 = 最后一個顏色,就完美了,就好看了
Demo放到github上面:
https://github.com/soyoungboy/SweepGradientProgress