Android实现圆弧形渐变色进度条

效果图:

我写的这篇博客个人感觉非常的不详细,这也是根据UI设计的,不过大家掌握下文所点出来的重点方法也可以将其绘制出来,这里就不详细介绍绘制流程了
Android实现圆弧形渐变色进度条_第1张图片

UI分析:

这个UI细分为表盘刻度、进度条底色、进度条渐变色、最外层那个实心圆球和文字描述。接下来就逐个实现

一、绘制表盘刻度

1、绘制表盘的刻度主要是用了画布的旋转来进行绘制
利用canvas.rotate()方法来旋转画布。利用canva.drawText()方法绘制文字,最后canvas.restore()释放画布让其回到原来的位置

/**
     * 旋转画布画刻度
     * @param canvas 画布
     */
    private void paintPercentText(Canvas canvas){
        paint.setTextSize(percentTextSize);
        paint.setColor(pinkColor);
        paint.setStrokeWidth(1);
        paint.setTextAlign(Paint.Align.CENTER);
        for (int i=0;i<=10;i++){
            //保存画布
            canvas.save();
            //旋转角度,第一个参数是旋转的角度、第二个参数和第三个参数是旋转中心点x和y
            canvas.rotate((float) (spaceAngle * i + -135 + spaceAngle), width / 2, radius);
            //画文字
            canvas.drawText(i * 10 + "", width / 2,  outerArcWidth + insideArcWidth + spaceWidth * 2, paint);
            canvas.restore();
        }
    }

二、绘制进度条底色

绘制进度条的底色主要用paint.setStrokeCap(Paint.Cap.ROUND)将画笔设置为圆角和canvas.drawArc()方法,这里就需要计算好矩形框以及起始的角度和结束的角度

 /**画两条线的底色*/
    private void paintPercentBack(Canvas canvas){
        paint.setColor(grayColor);
        paint.setStrokeWidth(outerArcWidth);//outerArcWidth
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);//设置为圆角
        paint.setAntiAlias(true);
        //绘制最外层圆条底色
        outerArcRadius=radius-outerArcWidth;
        outerArea= new RectF(width/2 - outerArcRadius, radius - outerArcRadius, width/2  + outerArcRadius, radius + outerArcRadius);
        canvas.drawArc(outerArea,
                (float) (180 - floatAngel),
                (float) (180 + 2 * floatAngel), false, paint);
        //绘制里层大宽度弧形
        paint.setColor(pinkColor);
        paint.setStrokeWidth(insideArcWidth);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(new RectF(width / 2 - insideArcRadius, radius - insideArcRadius, width / 2 + insideArcRadius, radius + insideArcRadius),
                (float) (180 - floatAngel),
                (float) (180 + 2 * floatAngel), false, paint);

    }

三、绘制进度条的渐变色

绘制渐变色的进度条主要是用到了setXfermode()方法setShader()方法和来进行绘制,setXfermode方法选择PorterDuff.Mode.SRC_ATOP是用于将绘制的内容显示在第一次绘制内容之上,(不过这个绘制应该在Bitmap上,最后的整体代码上有),setShader方法用于渐变色控制

四、绘制最外层的的原点

最外层的原点需要不断的计算坐标,在这里用到的方法主要是PathMeasure类,将要绘制的圆弧,加入一个路径,
private float[] pos; // 当前点的实际位置
private float[] tan; // 当前点的tangent值,
PathMeasure measure = new PathMeasure(orbit, false);
measure.getPosTan(measure.getLength() * 1, pos, tan);
获取路径的终点的正切值和坐标,然后根据坐标点绘制实心小园球

 private void paintPercent(double percent,double aimPercent,Canvas canvas){
        double roateAngel=percent*0.01*225;
        shaderPaint.setColor(yellowColor);
        shaderPaint.setStrokeCap(Paint.Cap.ROUND);
        shaderPaint.setAntiAlias(true);
        shaderPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));//shaderPaint.setColor(yellowColor);
        if (aimPercent>=0&&aimPercent<=20){
        }else if (aimPercent>20&&aimPercent<=60){
            int colorSweep[] = { yellowColor,pinkRedColor };
            float position[]={0.5f,0.7f};
            SweepGradient sweepGradient=new SweepGradient(width / 2, radius, colorSweep, position);
            shaderPaint.setShader(sweepGradient);
        }else if (aimPercent>60&&aimPercent<=90){
            int colorSweep[] = { yellowColor,pinkRedColor,redColor };
            float position[]={0.5f,0.7f,0.8f};
            SweepGradient sweepGradient=new SweepGradient(width / 2, radius, colorSweep, position);
            shaderPaint.setShader(sweepGradient);
        }else if (aimPercent>90){
            int colorSweep[] = {deepRedColor, yellowColor,yellowColor,pinkRedColor,redColor, deepRedColor};
            float position[]={0.2f,0.4f,0.5f,0.7f,0.9f,1.0f};
            SweepGradient sweepGradient=new SweepGradient(width / 2, radius, colorSweep, position);
            shaderPaint.setShader(sweepGradient);
        }
        if (aimPercent<=10){//目的是为了
            drawInsideArc((float) (180 - floatAngel), (float) roateAngel, canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) roateAngel, canvas,mBitmapBackDeepRed,yellowColor);
        }else if (aimPercent>10&&aimPercent<=20){
            drawInsideArc((float) (180 - floatAngel), (float) roateAngel, canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) roateAngel, canvas,mBitmapBackDeepRed,yellowColor);
        }else if (aimPercent>20&&aimPercent<=60){
            drawInsideArc((float) (180 - floatAngel), (float) (roateAngel-(spaceAngle-floatAngel)), canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) (roateAngel - (spaceAngle - floatAngel)), canvas,mBitmapBackDeepRed,pinkRedColor);
        }else if (aimPercent>60&&aimPercent<=90){
            drawInsideArc((float) (180 - floatAngel), (float) (roateAngel-(spaceAngle-floatAngel)), canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) (roateAngel - (spaceAngle - floatAngel)),canvas,mBitmapBackDeepRed,redColor);
        }else {
            drawInsideArc((float) (180 - floatAngel), (float) (roateAngel-2*(spaceAngle-floatAngel)), canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) (roateAngel-2*(spaceAngle-floatAngel)), canvas,mBitmapBackDeepRed, deepRedColor);
        }


    }

    /***
     * 画内部圆环渐变
     * @param formDegree 起始角度
     * @param toDegree 旋转角度
     * @param canvas 画布
     */
    private void drawInsideArc(float formDegree ,float toDegree,Canvas canvas){
        shaderPaint.setStrokeWidth(insideArcWidth);
        shaderPaint.setStyle(Paint.Style.STROKE);
        //内弧半径
        canvas.drawArc(new RectF(width / 2 - insideArcRadius, radius - insideArcRadius, width / 2 + insideArcRadius, radius + insideArcRadius),
                formDegree,
                toDegree, false, shaderPaint);

    }

    /***
     * 绘制外部彩色线条和小红圈
     * 利用PathMeasure的getTranslate测量出需要绘制的圆弧的末端的坐标位置
     * @param formDegree 起始角度
     * @param toDegree 旋转角度
     * @param canvas 画布
     * @param bitmap 四种状态的模糊Bitmap
     * @param color 四种状态的实心颜色
     */
    private void drawOuterAcr(float formDegree ,float toDegree,Canvas canvas,Bitmap bitmap,int color){
        shaderPaint.setStrokeWidth(outerArcWidth);
        shaderPaint.setStyle(Paint.Style.STROKE);
//        canvas.drawArc( new RectF(width/2 - outerArcRadius, radius - outerArcRadius, width/2  + outerArcRadius, radius + outerArcRadius),
//                formDegree,
//                toDegree, false, shaderPaint);
        Path orbit = new Path();
        //通过Path类画一个90度(180—270)的内切圆弧路径
        orbit.addArc(outerArea, formDegree, toDegree);
        // 创建 PathMeasure
        PathMeasure measure = new PathMeasure(orbit, false);
        measure.getPosTan(measure.getLength() * 1, pos, tan);
        mMatrix.reset();
        mMatrix.postTranslate(pos[0] - bitmap.getWidth() / 2, pos[1] - bitmap.getHeight() / 2);   // 将图片绘制中心调整到与当前点重合
        canvas.drawPath(orbit, shaderPaint);//绘制外层的线条
        canvas.drawBitmap(bitmap, mMatrix, bitmapPaint);//绘制
        bitmapPaint.setColor(color);
        //绘制实心小圆圈
        canvas.drawCircle(pos[0], pos[1], 8, bitmapPaint);
    }

五、绘制文字

绘制文字就简单了,不过为了绘制不同的颜色效果,需要测量一下文字的宽度这里用到的方法是Paint.measureText()方法

  /***
     * 4个色值由浅到深分别是 ffd200 ff5656 fa4040 f60157
     * 等级划分:0-20% 再接再厉   21-60% 技高一筹   61-90% 名列前茅   90以上 理财达人
     */
    private void paintText(Canvas canvas){
        if (!TextUtils.isEmpty(tag)&&!TextUtils.isEmpty(aim)){
            if (aimPercent>=0&&aimPercent<=20){
                textPaint.setColor(yellowColor);
            }else if (aimPercent>20&&aimPercent<=60){
                textPaint.setColor(pinkRedColor);
            }else if (aimPercent>60&&aimPercent<=90){
                textPaint.setColor(redColor);
            }else {
                textPaint.setColor(deepRedColor);
            }
            textPaint.setTextSize(textSizeTag);
            textPaint.setTextAlign(Paint.Align.CENTER);
            textPaint.setStrokeWidth(2);
            canvas.drawText(tag, width / 2, radius - textSizeTag / 2, textPaint);
            textPaint.setColor(grayColor);
            textPaint.setTextSize(textSizeAim);
            textPaint.setStrokeWidth(1);
            float leftLength=textPaint.measureText("你击败了");
            float rightLength=textPaint.measureText("的用户");
            float centerLength=textPaint.measureText(aim+"%");
            float rightOffest=textSizeAim/2;//
            canvas.drawText("你击败了",width/2-leftLength/2-centerLength/2+rightOffest,radius + textSizeAim, textPaint);
            canvas.drawText("的用户",width/2+rightLength/2+centerLength/2+rightOffest,radius + textSizeAim, textPaint);
            textPaint.setColor(Color.parseColor("#fa4040"));
            canvas.drawText(aim+"%",width/2+rightOffest,radius + textSizeAim, textPaint);

        }


    }

六、实现动画效果用的是ValueAnimator整体代码如下:

package com.lsl.huoqiu.widget;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.lsl.huoqiu.R;


/**
 * 用户击败百分比
 * 设计思路:首先定义最外层小圆点的半径,外层细圆弧的宽度,内存宽圆弧的宽度,两个圆弧中间间隔的宽度,
 * 然后利用旋转画布来绘制文本,接着绘制两个圆弧的底色,接着根据传过来的数据绘制渐变色圆弧和原点
 * 利用ValueAnimator来设置动画效果
 *
 * Created by Forrest on 16/8/12.
 */
public class PercentView extends View{
    private Paint paint;//画笔
    private Paint shaderPaint;//彩色画笔
    private Paint bitmapPaint;//图片画笔
    private Paint textPaint;//文字画笔
    /**控件宽度*/
    private int width;
    /**控件高度*/
    private int height;
    /**半径*/
    private int radius;
    /**外圆弧的宽度*/
    private float outerArcWidth;
    /**内部大圆弧的宽度*/
    private float insideArcWidth;
    /**两圆弧中间间隔距离*/
    private float spaceWidth;
    /**两圆弧中间间隔距离*/
    private float percentTextSize;
    /**最外层滑动小球的半径*/
    private float scrollCircleRadius;
    /**粉红底色*/
    private int pinkColor;
    /**黄色*/
    private int yellowColor;
    /**粉色红*/
    private int pinkRedColor;
    /**浅红*/
    private int redColor;
    /**深红*/
    private int deepRedColor;
    /**灰色*/
    private int grayColor;
    /**间隔的角度*/
    private double spaceAngle=22.5;
    /**两条圆弧的起始角度*/
    private double floatAngel=20;
    /**自定义的Bitmap*/
    private Bitmap mBitmap;
    /**自定义的画布,目的是为了能画出重叠的效果*/
    private Canvas mCanvas;
    /**时刻变化的Angel*/
    private double mAngel;
    /**内弧半径*/
    private float insideArcRadius;
    private double aimPercent=0;
    private float outerArcRadius;
    private float[] pos;                // 当前点的实际位置
    private float[] tan;                // 当前点的tangent值,用于计算图片所需旋转的角度
    private Bitmap mBitmapBackDeepRed;  // 箭头图片
    private Matrix mMatrix;             // 矩阵,用于对图片进行一些操作
    private RectF outerArea;            //外圈的矩形
    private String tag;
    private String aim;
    private int textSizeTag;//名列前茅字体大小
    private int textSizeAim;//击败百分比字体大小

    // 动效过程监听器
    private ValueAnimator.AnimatorUpdateListener mUpdateListener;
    private Animator.AnimatorListener mAnimatorListener;
    //过程动画
    private ValueAnimator mValueAnimator;
    // 用于控制动画状态转换
    private Handler mAnimatorHandler;
    // 默认的动效周期 2s
    private int defaultDuration = 2000;


    public PercentView(Context context) {
        super(context);
        initView(context);

    }

    public PercentView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);

    }

    public PercentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);

    }

    private void initView(Context context){
        shaderPaint=new Paint();
        textPaint=new Paint();

        paint=new Paint();
        paint.setStyle(Paint.Style.STROKE); //设置空心
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);

        bitmapPaint=new Paint();
        bitmapPaint.setStyle(Paint.Style.FILL);
        bitmapPaint.setAntiAlias(true);

        outerArcWidth = context.getResources().getDimensionPixelOffset(R.dimen.dp2);
        insideArcWidth = context.getResources().getDimensionPixelOffset(R.dimen.dp12);
        spaceWidth = context.getResources().getDimensionPixelOffset(R.dimen.dp12);
        scrollCircleRadius = context.getResources().getDimensionPixelOffset(R.dimen.dp4);
        percentTextSize = context.getResources().getDimensionPixelOffset(R.dimen.dp8);
        textSizeAim = context.getResources().getDimensionPixelOffset(R.dimen.sp15);
        textSizeTag = context.getResources().getDimensionPixelOffset(R.dimen.sp30);
        pinkColor = context.getResources().getColor(R.color.percent_pink);
        yellowColor = context.getResources().getColor(R.color.percent_yellow);
        pinkRedColor = context.getResources().getColor(R.color.percent_pink_red);
        redColor = context.getResources().getColor(R.color.percent_red);
        deepRedColor = context.getResources().getColor(R.color.percent_deep_red);
        grayColor = context.getResources().getColor(R.color.percent_gray);


        pos = new float[2];
        tan = new float[2];
        mBitmapBackDeepRed= BitmapFactory.decodeResource(context.getResources(), R.mipmap.blur_back_deep_red);
        mMatrix=new Matrix();

    }

    private int count=0;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.i("PercentVIew", "开始绘制" + count);
        long startTime=System.currentTimeMillis();
        count++;
        width = getWidth(); //获取宽度
        height = getHeight();//获取高度
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvas =new Canvas(mBitmap);

        radius= (int) (height/(1+Math.sin(Math.toRadians(spaceAngle))));//获取最外园的半径
        insideArcRadius= radius-scrollCircleRadius-spaceWidth;//内弧半径
//        Log.i(TAG,"最外园半径"+radius+"\n高度为"+height);
//        Log.i(TAG,"最外园半径"+Math.sin(Math.toRadians(spaceAngle)));
        paintPercentText(mCanvas);
        paintPercentBack(mCanvas);
        paintPercent(mAngel, aimPercent, mCanvas);
//        calculateItemPositions(aimPercent,increaseValue,mCanvas,mBitmapBackDeepRed);
        //将Bitmap画到Canvas
        paintText(mCanvas);
        canvas.drawBitmap(mBitmap, 0, 0, null);
        long endTime=System.currentTimeMillis();
        Log.i("PercentVIew", "绘制结束" + (endTime-startTime));
    }

    /**
     * 旋转画布画刻度
     * @param canvas 画布
     */
    private void paintPercentText(Canvas canvas){
        paint.setTextSize(percentTextSize);
        paint.setColor(pinkColor);
        paint.setStrokeWidth(1);
        paint.setTextAlign(Paint.Align.CENTER);
        for (int i=0;i<=10;i++){
            //保存画布
            canvas.save();
            //旋转角度,第一个参数是旋转的角度、第二个参数和第三个参数是旋转中心点x和y
            canvas.rotate((float) (spaceAngle * i + -135 + spaceAngle), width / 2, radius);
            //画文字
            canvas.drawText(i * 10 + "", width / 2,  outerArcWidth + insideArcWidth + spaceWidth * 2, paint);
            canvas.restore();
        }
    }
    /**画两条线的底色*/
    private void paintPercentBack(Canvas canvas){
        paint.setColor(grayColor);
        paint.setStrokeWidth(outerArcWidth);//outerArcWidth
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);//设置为圆角
        paint.setAntiAlias(true);
        //绘制最外层圆条底色
        outerArcRadius=radius-outerArcWidth;
        outerArea= new RectF(width/2 - outerArcRadius, radius - outerArcRadius, width/2  + outerArcRadius, radius + outerArcRadius);
        canvas.drawArc(outerArea,
                (float) (180 - floatAngel),
                (float) (180 + 2 * floatAngel), false, paint);
        //绘制里层大宽度弧形
        paint.setColor(pinkColor);
        paint.setStrokeWidth(insideArcWidth);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(new RectF(width / 2 - insideArcRadius, radius - insideArcRadius, width / 2 + insideArcRadius, radius + insideArcRadius),
                (float) (180 - floatAngel),
                (float) (180 + 2 * floatAngel), false, paint);

    }

    /***
     * 4个色值由浅到深分别是 ffd200 ff5656 fa4040 f60157
     * 等级划分:0-20% 再接再厉   21-60% 技高一筹   61-90% 名列前茅   90以上 理财达人
     * 绘制外层和内层的颜色线条
     * 主要用到Xfermode的SRC_ATOP显示上层绘制
     * setStrokeCap   Paint.Cap.ROUND设置为圆角矩形
     */
    private void paintPercent(double percent,double aimPercent,Canvas canvas){
        double roateAngel=percent*0.01*225;
        shaderPaint.setColor(yellowColor);
        shaderPaint.setStrokeCap(Paint.Cap.ROUND);
        shaderPaint.setAntiAlias(true);
        shaderPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));//shaderPaint.setColor(yellowColor);
        if (aimPercent>=0&&aimPercent<=20){
        }else if (aimPercent>20&&aimPercent<=60){
            int colorSweep[] = { yellowColor,pinkRedColor };
            float position[]={0.5f,0.7f};
            SweepGradient sweepGradient=new SweepGradient(width / 2, radius, colorSweep, position);
            shaderPaint.setShader(sweepGradient);
        }else if (aimPercent>60&&aimPercent<=90){
            int colorSweep[] = { yellowColor,pinkRedColor,redColor };
            float position[]={0.5f,0.7f,0.8f};
            SweepGradient sweepGradient=new SweepGradient(width / 2, radius, colorSweep, position);
            shaderPaint.setShader(sweepGradient);
        }else if (aimPercent>90){
            int colorSweep[] = {deepRedColor, yellowColor,yellowColor,pinkRedColor,redColor, deepRedColor};
            float position[]={0.2f,0.4f,0.5f,0.7f,0.9f,1.0f};
            SweepGradient sweepGradient=new SweepGradient(width / 2, radius, colorSweep, position);
            shaderPaint.setShader(sweepGradient);
        }
        if (aimPercent<=10){//目的是为了
            drawInsideArc((float) (180 - floatAngel), (float) roateAngel, canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) roateAngel, canvas,mBitmapBackDeepRed,yellowColor);
        }else if (aimPercent>10&&aimPercent<=20){
            drawInsideArc((float) (180 - floatAngel), (float) roateAngel, canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) roateAngel, canvas,mBitmapBackDeepRed,yellowColor);
        }else if (aimPercent>20&&aimPercent<=60){
            drawInsideArc((float) (180 - floatAngel), (float) (roateAngel-(spaceAngle-floatAngel)), canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) (roateAngel - (spaceAngle - floatAngel)), canvas,mBitmapBackDeepRed,pinkRedColor);
        }else if (aimPercent>60&&aimPercent<=90){
            drawInsideArc((float) (180 - floatAngel), (float) (roateAngel-(spaceAngle-floatAngel)), canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) (roateAngel - (spaceAngle - floatAngel)),canvas,mBitmapBackDeepRed,redColor);
        }else {
            drawInsideArc((float) (180 - floatAngel), (float) (roateAngel-2*(spaceAngle-floatAngel)), canvas);
            drawOuterAcr((float) (180 - floatAngel), (float) (roateAngel-2*(spaceAngle-floatAngel)), canvas,mBitmapBackDeepRed, deepRedColor);
        }


    }

    /***
     * 画内部圆环渐变
     * @param formDegree 起始角度
     * @param toDegree 旋转角度
     * @param canvas 画布
     */
    private void drawInsideArc(float formDegree ,float toDegree,Canvas canvas){
        shaderPaint.setStrokeWidth(insideArcWidth);
        shaderPaint.setStyle(Paint.Style.STROKE);
        //内弧半径
        canvas.drawArc(new RectF(width / 2 - insideArcRadius, radius - insideArcRadius, width / 2 + insideArcRadius, radius + insideArcRadius),
                formDegree,
                toDegree, false, shaderPaint);

    }

    /***
     * 绘制外部彩色线条和小红圈
     * 利用PathMeasure的getTranslate测量出需要绘制的圆弧的末端的坐标位置
     * @param formDegree 起始角度
     * @param toDegree 旋转角度
     * @param canvas 画布
     * @param bitmap 四种状态的模糊Bitmap
     * @param color 四种状态的实心颜色
     */
    private void drawOuterAcr(float formDegree ,float toDegree,Canvas canvas,Bitmap bitmap,int color){
        shaderPaint.setStrokeWidth(outerArcWidth);
        shaderPaint.setStyle(Paint.Style.STROKE);
//        canvas.drawArc( new RectF(width/2 - outerArcRadius, radius - outerArcRadius, width/2  + outerArcRadius, radius + outerArcRadius),
//                formDegree,
//                toDegree, false, shaderPaint);
        Path orbit = new Path();
        //通过Path类画一个90度(180—270)的内切圆弧路径
        orbit.addArc(outerArea, formDegree, toDegree);
        // 创建 PathMeasure
        PathMeasure measure = new PathMeasure(orbit, false);
        measure.getPosTan(measure.getLength() * 1, pos, tan);
        mMatrix.reset();
        mMatrix.postTranslate(pos[0] - bitmap.getWidth() / 2, pos[1] - bitmap.getHeight() / 2);   // 将图片绘制中心调整到与当前点重合
        canvas.drawPath(orbit, shaderPaint);//绘制外层的线条
        canvas.drawBitmap(bitmap, mMatrix, bitmapPaint);//绘制
        bitmapPaint.setColor(color);
        //绘制实心小圆圈
        canvas.drawCircle(pos[0], pos[1], 8, bitmapPaint);
    }
    /***
     * 4个色值由浅到深分别是 ffd200 ff5656 fa4040 f60157
     * 等级划分:0-20% 再接再厉   21-60% 技高一筹   61-90% 名列前茅   90以上 理财达人
     */
    private void paintText(Canvas canvas){
        if (!TextUtils.isEmpty(tag)&&!TextUtils.isEmpty(aim)){
            if (aimPercent>=0&&aimPercent<=20){
                textPaint.setColor(yellowColor);
            }else if (aimPercent>20&&aimPercent<=60){
                textPaint.setColor(pinkRedColor);
            }else if (aimPercent>60&&aimPercent<=90){
                textPaint.setColor(redColor);
            }else {
                textPaint.setColor(deepRedColor);
            }
            textPaint.setTextSize(textSizeTag);
            textPaint.setTextAlign(Paint.Align.CENTER);
            textPaint.setStrokeWidth(2);
            canvas.drawText(tag, width / 2, radius - textSizeTag / 2, textPaint);
            textPaint.setColor(grayColor);
            textPaint.setTextSize(textSizeAim);
            textPaint.setStrokeWidth(1);
            float leftLength=textPaint.measureText("你击败了");
            float rightLength=textPaint.measureText("的用户");
            float centerLength=textPaint.measureText(aim+"%");
            float rightOffest=textSizeAim/2;//
            canvas.drawText("你击败了",width/2-leftLength/2-centerLength/2+rightOffest,radius + textSizeAim, textPaint);
            canvas.drawText("的用户",width/2+rightLength/2+centerLength/2+rightOffest,radius + textSizeAim, textPaint);
            textPaint.setColor(Color.parseColor("#fa4040"));
            canvas.drawText(aim+"%",width/2+rightOffest,radius + textSizeAim, textPaint);

        }


    }

    /**
     * 设置角度变化,刷新界面
     * @param aimPercent 目标百分比
     */
    public void setAngel(double aimPercent){
        //两边监测
        if (aimPercent<1){
            aimPercent=1;
        }else if (aimPercent>99){
            aimPercent=99;
        }
        this.aimPercent=aimPercent;
        initListener();

        initHandler();

        initAnimator();
        mValueAnimator.start();

    }

    /**
     * 设置文字
     * @param tag 名列前茅文案
     * @param aim 击败的百分比
     */
    public void setRankText(String tag,String aim){
        this.tag=tag;
        this.aim=aim;
        mAnimatorHandler.sendEmptyMessage(1);

    }

    private void initListener() {
        mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAngel = (float) animation.getAnimatedValue()*aimPercent;
//                Log.i("TAG", "mAnimatorValue="+mAnimatorValue);
                invalidate();
            }
        };

        mAnimatorListener = new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                // getHandle发消息通知动画状态更新
                mAnimatorHandler.sendEmptyMessage(0);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        };
    }

    private void initHandler() {
        mAnimatorHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case 0:
                        mValueAnimator.removeAllUpdateListeners();
                        mValueAnimator.removeAllListeners();
                        break;
                    case 1:
                        invalidate();
                        break;
                }

            }
        };
    }

    private void initAnimator() {
        mValueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);

        mValueAnimator.addUpdateListener(mUpdateListener);

        mValueAnimator.addListener(mAnimatorListener);
    }


}


你可能感兴趣的:(Android)