FanProgressBar,关于Canvas的一点体会

来源:互联网 发布:jiaoben linux 反斜线 编辑:程序博客网 时间:2024/06/04 19:26

公司项目想做个渐变效果,虽然最终没有实现出来,还是把自己的一点体会写出来。算是根据现象推测实现吧,没去研究源码怎么实现的。

直接上代码:

package com.wedgits;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.graphics.SweepGradient;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.View;import com.puhui.lib.utils.DensityUtil;import com.renren.customview.R;/** * Copyright: ******* * Created by ******* on 2017/5/9. * Description:  环形进度 * Modified By: */public class FanProgressBar extends View {    /**     * 画笔对象的引用     */    private Paint circlePaint;  //底部圆环画笔    private Paint arcPaint;  //上部圆弧画笔    private Paint topCirclePoint;  //顶部圆点    private Path mPath;    private boolean capRound;  //画笔形状    private int roundColor;  //圆环的颜色    private int roundProgressColor;  //圆弧进度的颜色    private float roundWidth;  //圆环的宽度    private int maxProgress = 100;  //最大进度    private float progress;  //当前进度    private int style = STROKE;  //进度的风格,实心或者空心    public static final int STROKE = 0;    public static final int FILL = 1;    public FanProgressBar(Context context) {        this(context, null);    }    public FanProgressBar(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public FanProgressBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.FanProgressBar);        // 获取自定义属性和默认值        roundColor = mTypedArray.getColor(R.styleable.FanProgressBar_bgColor, Color.RED);        roundProgressColor = mTypedArray.getColor(R.styleable.FanProgressBar_fgColor, Color.GREEN);        roundWidth = mTypedArray.getDimension(R.styleable.FanProgressBar_fanRoundWidth, DensityUtil.dip2px(getContext(), 15));        progress = mTypedArray.getInt(R.styleable.FanProgressBar_fanProgress, 0);        capRound = mTypedArray.getBoolean(R.styleable.FanProgressBar_capRound, true);        mTypedArray.recycle();    }    private RectF mOval;    private SweepGradient sweepGradient;    private static final int[] colors = new int[]{Color.GREEN, Color.GREEN, Color.BLUE, Color.RED, Color.RED};    private float circleSize;    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        float size = Math.min(w, h);        circleSize = size;        mOval = new RectF(roundWidth / 2, roundWidth / 2, size - roundWidth / 2, size - roundWidth / 2);        init();    }    /**     * 初始化操作     */    private void init() {        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);        circlePaint.setColor(roundColor); // 设置圆环的颜色        circlePaint.setStyle(Paint.Style.STROKE); // 设置空心        circlePaint.setStrokeWidth(roundWidth); // 设置圆环的宽度        circlePaint.setAntiAlias(true); // 消除锯齿        circlePaint.setStrokeCap(capRound ? Paint.Cap.ROUND : Paint.Cap.SQUARE);        sweepGradient = new SweepGradient(mOval.centerX(), mOval.centerY(), colors, null);        arcPaint = new Paint();//        arcPaint.setColor(roundProgressColor); // 设置圆环的颜色        arcPaint.setStyle(Paint.Style.STROKE); // 设置空心        arcPaint.setStrokeWidth(roundWidth); // 设置圆环的宽度        arcPaint.setAntiAlias(true); // 消除锯齿        arcPaint.setStrokeCap(capRound ? Paint.Cap.ROUND : Paint.Cap.SQUARE);        arcPaint.setShader(sweepGradient);        mPath = new Path();//        mPath.reset();//        mPath.addArc(mOval, 30, maxProgress);        topCirclePoint = new Paint();        topCirclePoint.setColor(ContextCompat.getColor(getContext(), R.color.white)); // 设置圆环的颜色        topCirclePoint.setStyle(Paint.Style.FILL_AND_STROKE);        topCirclePoint.setAntiAlias(true); // 消除锯齿    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.rotate(-120, circleSize / 2, circleSize / 2);        canvas.save();        canvas.drawArc(mOval, 0, 360, false, circlePaint); // 画出圆环        //画圆弧 ,画圆环的进度//        arcPaint.setColor(roundProgressColor); // 设置进度的颜色//        arcPaint.setShader(sweepGradient);        switch (style) {            case STROKE: {//                Paint p = new Paint();//                参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像//                Gradient是基于Shader类,所以我们通过PaintsetShader方法来设置这个渐变//                LinearGradient lg = new LinearGradient(0, 0, 400, 400, colors, positions, Shader.TileMode.MIRROR);//                arcPaint.setShader(lg);//                mPath.reset();//                mPath.addArc(mOval, 30, progress);//                canvas.drawPath(mPath, arcPaint);                canvas.drawArc(mOval, 30, progress, false, arcPaint); // 根据进度画圆弧                break;            }            case FILL: {                arcPaint.setStyle(Paint.Style.FILL_AND_STROKE);                if (progress != 0)                    canvas.drawArc(mOval, 0, 360 * progress / maxProgress, true, arcPaint); // 根据进度画圆弧                break;            }        }        canvas.drawCircle(mOval.centerX(), roundWidth / 2, DensityUtil.dip2px(getContext(), 4), topCirclePoint);        canvas.restore();    }    /**     * 获取进度.需要同步     */    public synchronized float getProgress() {        return progress;    }    public void setMaxProgress(int maxProgress) {        this.maxProgress = maxProgress;    }    public int getMaxProgress() {        return maxProgress;    }    /**     * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 刷新界面调用postInvalidate()能在非UI线程刷新     */    public void setProgress(int progress) {        if (progress < 0) {            progress = 0;        }        if (progress > maxProgress) {            progress = maxProgress;        }        setAnimation(progress);    }    /**     * 为进度设置动画     */    public void setAnimation(float progress) {        ValueAnimator progressAnimator = ValueAnimator.ofFloat(0, progress);        progressAnimator.setDuration(3000);        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                FanProgressBar.this.progress = (float) animation.getAnimatedValue();                invalidate();            }        });        progressAnimator.start();    }}
样式文件:
<declare-styleable name="FanProgressBar">    <attr name="bgColor" format="color" />    <attr name="fgColor" format="color" />    <attr name="fanRoundWidth" format="dimension" />    <attr name="fanProgress" format="integer" />    <attr name="capRound" format="boolean" /></declare-styleable>
使用:

LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) fanProgressBar.getLayoutParams();layoutParams.width = DensityUtil.getScreenWidth(this) - DensityUtil.dip2px(this, 120);layoutParams.height = DensityUtil.getScreenWidth(this) - DensityUtil.dip2px(this, 120);fanProgressBar.setLayoutParams(layoutParams);fanProgressBar.setMaxProgress(360);fanProgressBar.setAnimation(fanProgressBar.getMaxProgress());

效果一:


效果二:


效果三:



效果四:(onDraw方法部分代码同效果三)


唉,纠结该怎么描述。

不管了,瞎说吧。

一、在我们给Paint设置shader(arcPaint.setShader(sweepGradient);)时,圆环的颜色占比就已经分配好了new int[]{Color.GREEN, Color.GREEN, Color.BLUE, Color.RED, Color.RED};,Green : Blue : Red = 2 : 1 : 2。而且是分配在整个圆环的。所以在Progress设置为360,200,120时,出现不同的效果,如效果一,效果四。


二、



原创粉丝点击