自定義控件之圓形顏色漸變進度條--SweepGradient


 

前幾天在群里面有人找圓形可顏色漸變進度條,其中主要的知識點是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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM