使用Xfermode绘制一个颜色渐变的圆形进度条

来源:互联网 发布:搜狐网络大厦地址 编辑:程序博客网 时间:2024/05/22 08:22
package com.example.administrator.cycleprogressview;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.graphics.drawable.GradientDrawable;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.animation.AccelerateDecelerateInterpolator;/** * Created by zq_zhan on 2017/2/28. */public class CycleProgressView extends View {    public CycleProgressView(Context context) {        this(context,null);    }    public CycleProgressView(Context context, AttributeSet attrs) {        this(context,attrs,0);    }    public CycleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private int width;    private int height;    private float max;    private float progress;    private float angle;    private int unit;    private float unitAngle;    private Paint cyclePaint;    private Paint linPaint;    private Paint ballPaint;    private RectF rectF;    private int min;    private int ballRadio;    private int cycleWidth;    private int topColor;    private int bottomColor;    private Bitmap mixtureBitmap;    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        width = getMeasuredWidth();        height = getMeasuredHeight();        min = Math.min(width,height)/2-20;        rectF = new RectF(width/2-min,height/2-min,width/2+min,height/2+min);        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    public void setMax(float max){        this.max = max;    }    public void setProgress(float progress){        this.progress = progress;        doAnimation();    }    private void updateProgress(float progress){        angle = progress/max*270;        invalidate();    }    public void setUnit(int unit){        this.unit = unit;        unitAngle = 270/max*unit;    }    public void setTopColor(int topColor){        this.topColor = topColor;        mDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {topColor,bottomColor});    }    public void setBottomColor(int bottomColor){        this.bottomColor = bottomColor;        mDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {topColor,bottomColor});    }    private void init(){        ballRadio = 10;        cycleWidth = 50;        angle = 86;        unitAngle = 3;        cyclePaint = new Paint();        cyclePaint.setColor(Color.BLUE);        cyclePaint.setStyle(Paint.Style.STROKE);        cyclePaint.setStrokeWidth(50);        cyclePaint.setAntiAlias(true);        linPaint = new Paint();        linPaint.setColor(Color.BLUE);        linPaint.setStyle(Paint.Style.STROKE);        linPaint.setStrokeWidth(2);        linPaint.setStrokeCap(Paint.Cap.ROUND);        linPaint.setAntiAlias(true);        ballPaint = new Paint();        ballPaint.setColor(Color.BLUE);        ballPaint.setStyle(Paint.Style.FILL);        ballPaint.setAntiAlias(true);        topColor = getResources().getColor(R.color.colorAccen);        bottomColor = getResources().getColor(R.color.colorAccen1);        //颜色渐变Drawable;        mDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {topColor,bottomColor});    }    GradientDrawable mDrawable;    private void drawStrokeCycle(Canvas canvas){        //将Drawable转换成bitmap        mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);        mDrawable.setBounds(0,0,width,height);        mDrawable.setSize(width,height);        mixtureBitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);        Canvas canvas1 = new Canvas(mixtureBitmap);        mDrawable.draw(canvas1);        //使用Xfermode将渐变drawable转换的bitmap和想绘制的图形进行求交集即可绘制一个颜色渐变的图形        int layerId = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);        //使用Xfermode前要关闭硬件加速,不然会达不到想要的效果        setLayerType(LAYER_TYPE_HARDWARE, null);        canvas.drawCircle(width/2,height/2,min-cycleWidth/2-ballRadio,cyclePaint);        cyclePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        canvas.drawBitmap(mixtureBitmap,null,rectF,cyclePaint);        cyclePaint.setXfermode(null);        canvas.restoreToCount(layerId);    }    private void drawScale(Canvas canvas){        float addAngle = 0;        while(addAngle<angle){            linPaint.setColor(Color.WHITE);            linPaint.setStrokeWidth(2);            canvas.drawLine(width/2-min+20,height/2,width/2-min+45,height/2,linPaint);            canvas.rotate(unitAngle,width/2,height/2);            addAngle += unitAngle;        }        canvas.rotate(angle-addAngle,width/2,height/2);        linPaint.setStrokeWidth(5);        canvas.drawLine(width/2-min+17,height/2,width/2-min+50,height/2,linPaint);        drawBall(canvas);    }    private void drawBall(Canvas canvas){        ballPaint.setColor(Color.WHITE);        linPaint.setStrokeWidth(1);        linPaint.setColor(Color.GREEN);        canvas.drawCircle(width/2-min,height/2,18,ballPaint);        canvas.drawCircle(width/2-min,height/2,18,linPaint);        ballPaint.setColor(Color.GREEN);        canvas.drawCircle(width/2-min,height/2,10,ballPaint);    }    private float[] calculateBallCenter(){        float[] center = new float[2];        float dy = (float) (Math.sin(Math.toRadians(angle))*min);        float dx = (float) (Math.cos(Math.toRadians(angle))*min);        center[0]= width/2 - dx;        center[1] = height/2 - dy;        return center;    }    @Override    protected void onDraw(Canvas canvas) {        drawStrokeCycle(canvas);        canvas.rotate(-45,width/2,height/2);        linPaint.setColor(Color.GREEN);        linPaint.setStrokeWidth(3);        canvas.drawArc(rectF,-180,angle,false,linPaint);        drawScale(canvas);        super.onDraw(canvas);    }    //动画效果    private void doAnimation(){        ValueAnimator animator = ValueAnimator.ofFloat(0,1);        animator.setDuration(1500);        animator.setInterpolator(new AccelerateDecelerateInterpolator());        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float currentValue = (float) animation.getAnimatedValue();                float progress1 = progress*currentValue;                updateProgress(progress1);            }        });        animator.start();    }}


0 0
原创粉丝点击