27
2017
09

两个弧形的progressBar

这里写图片描述

/** * 颜色弧形进度条 http://www.jcodecraeer.com/a/opensource/2016/0228/4010.html * Created by yangmingguang on 2016/7/5. */
public class DoubleArcProgressBar extends View {

    private final static int ANIMATOR_DURATION = 500;

    //开始角度
    private float mStartAngle;
    //角度
    private float mAngle;


    //内部弧形相关
    private Paint mInsideArcPaint;
    private int mInsideArcColor;
    private int mInsideProgressArcColor;
    private int mInsideArcWidth;
    private int mInsideRadius;
    private int mInsideValue;
    private int mInsideMax;
    private RectF mInsideRect;

    //外部弧形相关
    private Paint mExtArcPaint;
    private int mExtArcColor;
    private int mExtProgressArcColor;
    private int mExtArcWidth;
    private int mExtRadius;
    private int mExtValue;
    private int mExtMax;
    private RectF mExtRect;

    //-----------文字相关-------------
    //从上往下
    private Paint mText1Paint;
    private int mText1Color;
    private int mText1Size;
    private String mText1;
    private Paint mText2Paint;
    private int mText2Color;
    private int mText2Size;
    private String mText2;
    private Paint mText3Paint;
    private int mText3Color;
    private int mText3Size;
    private String mText3;
    private Paint mText4Paint;
    private int mText4Color;
    private int mText4Size;
    private String mText4;

    private Rect mRectText;

    private PaintFlagsDrawFilter mDrawFilter;
    private ValueAnimator mProgressAnimator;
    //动画使用
    private int mInsideCurValue;
    private int mExtCurValue;

    public DoubleArcProgressBar(Context context) {
        this(context, null);
    }

    public DoubleArcProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DoubleArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initConfig(context, attrs);
        initUtil();
    }

    /** * 初始化布局配置 */
    private void initConfig(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DoubleArcProgressBar);
        mStartAngle = a.getFloat(R.styleable.DoubleArcProgressBar_drpb_start_angle, 135);
        mAngle = a.getFloat(R.styleable.DoubleArcProgressBar_drpb_angle, 270);

        mInsideArcColor = a.getColor(R.styleable.DoubleArcProgressBar_drpb_inside_color, Color.GRAY);
        mInsideProgressArcColor = a.getColor(R.styleable.DoubleArcProgressBar_drpb_inside_progress_color, Color.GREEN);
        mInsideArcWidth = a.getDimensionPixelOffset(R.styleable.DoubleArcProgressBar_drpb_inside_width, dp2px(4));
        mInsideMax = a.getInteger(R.styleable.DoubleArcProgressBar_drpb_inside_max, 100);
        mInsideValue = a.getColor(R.styleable.DoubleArcProgressBar_drpb_inside_value, 10);
        mInsideRadius = a.getDimensionPixelOffset(R.styleable.DoubleArcProgressBar_drpb_inside_radius, dp2px(35));

        mExtArcColor = a.getColor(R.styleable.DoubleArcProgressBar_drpb_ext_color, Color.GRAY);
        mExtProgressArcColor = a.getColor(R.styleable.DoubleArcProgressBar_drpb_ext_progress_color, Color.GREEN);
        mExtArcWidth = a.getDimensionPixelOffset(R.styleable.DoubleArcProgressBar_drpb_ext_width, dp2px(4));
        mExtMax = a.getInteger(R.styleable.DoubleArcProgressBar_drpb_ext_max, 100);
        mExtValue = a.getColor(R.styleable.DoubleArcProgressBar_drpb_ext_value, 20);
        mExtRadius = a.getDimensionPixelOffset(R.styleable.DoubleArcProgressBar_drpb_ext_radius, dp2px(43));


        mText1Color = a.getColor(R.styleable.DoubleArcProgressBar_drpb_text1_color, Color.WHITE);
        mText1Size = a.getDimensionPixelSize(R.styleable.DoubleArcProgressBar_drpb_text1_size, sp2px(12));
        mText1 = a.getString(R.styleable.DoubleArcProgressBar_drpb_text1);
        mText2Color = a.getColor(R.styleable.DoubleArcProgressBar_drpb_text2_color, Color.WHITE);
        mText2Size = a.getDimensionPixelSize(R.styleable.DoubleArcProgressBar_drpb_text2_size, sp2px(12));
        mText2 = a.getString(R.styleable.DoubleArcProgressBar_drpb_text2);
        mText3Color = a.getColor(R.styleable.DoubleArcProgressBar_drpb_text3_color, Color.WHITE);
        mText3Size = a.getDimensionPixelSize(R.styleable.DoubleArcProgressBar_drpb_text3_size, sp2px(12));
        mText3 = a.getString(R.styleable.DoubleArcProgressBar_drpb_text3);
        mText4Color = a.getColor(R.styleable.DoubleArcProgressBar_drpb_text4_color, Color.WHITE);
        mText4Size = a.getDimensionPixelSize(R.styleable.DoubleArcProgressBar_drpb_text4_size, sp2px(12));
        mText4 = a.getString(R.styleable.DoubleArcProgressBar_drpb_text4);
        a.recycle();

    }

    private void initUtil() {

        mInsideArcPaint = new Paint();
        mInsideArcPaint.setAntiAlias(true);
        mInsideArcPaint.setStyle(Paint.Style.STROKE);
        mInsideArcPaint.setStrokeWidth(mInsideArcWidth);
        mInsideArcPaint.setColor(mInsideArcColor);
        mInsideArcPaint.setStrokeCap(Paint.Cap.ROUND);

        mExtArcPaint = new Paint();
        mExtArcPaint.setAntiAlias(true);
        mExtArcPaint.setStyle(Paint.Style.STROKE);
        mExtArcPaint.setStrokeWidth(mExtArcWidth);
        mExtArcPaint.setColor(mExtArcColor);
        mExtArcPaint.setStrokeCap(Paint.Cap.ROUND);

        mText1Paint = new Paint();
        mText1Paint.setAntiAlias(true);
        mText1Paint.setTextSize(mText1Size);
        mText1Paint.setColor(mText1Color);
        mText1Paint.setTextAlign(Paint.Align.CENTER);

        mText2Paint = new Paint();
        mText2Paint.setAntiAlias(true);
        mText2Paint.setTextSize(mText2Size);
        mText2Paint.setColor(mText2Color);
        mText2Paint.setTextAlign(Paint.Align.CENTER);

        mText3Paint = new Paint();
        mText3Paint.setAntiAlias(true);
        mText3Paint.setTextSize(mText3Size);
        mText3Paint.setColor(mText3Color);
        mText3Paint.setTextAlign(Paint.Align.CENTER);

        mText4Paint = new Paint();
        mText4Paint.setAntiAlias(true);
        mText4Paint.setTextSize(mText4Size);
        mText4Paint.setColor(mText4Color);
        mText4Paint.setTextAlign(Paint.Align.CENTER);

        mRectText = new Rect();
        mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getPaddingLeft() + getPaddingRight();
        int height = getPaddingTop() + getPaddingBottom();
        width += mExtRadius * 2 + mExtArcWidth;
        height += mExtRadius * 2 + getFontHeight(mText4Paint, mText4Size) / 2 + mExtArcWidth;
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //抗锯齿
        canvas.setDrawFilter(mDrawFilter);

        drawInsideArc(canvas);
        drawExtArc(canvas);
        drawText(canvas);

    }

    /** * 绘制内部弧形 */
    private void drawInsideArc(Canvas canvas) {
        if (mInsideRect == null) {
            mInsideRect = new RectF();
            mInsideRect.left = getCenterX() - mInsideRadius - mInsideArcWidth / 2;
            mInsideRect.top = getCenterY() - mInsideRadius - mInsideArcWidth / 2;
            mInsideRect.right = getCenterX() + mInsideRadius + mInsideArcWidth / 2;
            mInsideRect.bottom = getCenterY() + mInsideRadius + mInsideArcWidth / 2;
        }

        mInsideArcPaint.setColor(mInsideArcColor);
        canvas.drawArc(mInsideRect, mStartAngle, mAngle, false, mInsideArcPaint);

        float angle = (mInsideCurValue * 1.0f / mInsideMax) * mAngle;
        if (angle <= 0) {
            return;
        }
        mInsideArcPaint.setColor(mInsideProgressArcColor);
        canvas.drawArc(mInsideRect, mStartAngle, angle, false, mInsideArcPaint);
    }

    /** * 绘制外部弧形 */
    private void drawExtArc(Canvas canvas) {
        if (mExtRect == null) {
            mExtRect = new RectF();
            mExtRect.left = getCenterX() - mExtRadius - mExtArcWidth / 2;
            mExtRect.top = getCenterY() - mExtRadius - mExtArcWidth / 2;
            mExtRect.right = getCenterX() + mExtRadius + mExtArcWidth / 2;
            mExtRect.bottom = getCenterY() + mExtRadius + mExtArcWidth / 2;
        }
        mExtArcPaint.setColor(mExtArcColor);
        canvas.drawArc(mExtRect, mStartAngle, mAngle, false, mExtArcPaint);

        float angle = (mExtCurValue * 1.0f / mExtMax) * mAngle;
        if (angle <= 0) {
            return;
        }
        mExtArcPaint.setColor(mExtProgressArcColor);
        canvas.drawArc(mExtRect, mStartAngle, angle, false, mExtArcPaint);
    }

    /** * 绘制文字 * * @param canvas */
    private void drawText(Canvas canvas) {
        int x = 0;
        int y = 0;
        boolean text1IsNotEmp = mText1 != null && !mText1.isEmpty();
        boolean text2IsNotEmp = mText2 != null && !mText2.isEmpty();
        boolean text3IsNotEmp = mText3 != null && !mText3.isEmpty();
        boolean text4IsNotEmp = mText4 != null && !mText4.isEmpty();


        if (text1IsNotEmp) {
            x = getCenterX();
            y = getCenterY() - getFontHeight(mText1Paint, mText1Size);
            if (text2IsNotEmp) {
                y = y + getFontHeight(mText2Paint, mText2Size) / 3 + dp2px(2);
            }

            canvas.drawText(mText1, x, y, mText1Paint);
        }

        if (text2IsNotEmp) {
            x = getCenterX();
            y = getCenterY() + getFontHeight(mText2Paint, mText2Size) / 3;

            canvas.drawText(mText2, x, y, mText2Paint);
        }

        if (text3IsNotEmp) {
            x = getCenterX();
            y = getCenterY() + mExtRadius - getFontHeight(mText3Paint, mText3Size) + dp2px(2);
            canvas.drawText(mText3, x, y, mText3Paint);
        }

        if (text4IsNotEmp) {
            x = getCenterX();
            y = getCenterY() + mExtRadius;
            canvas.drawText(mText4, x, y, mText4Paint);
        }
    }

    /** * 获取圆心x坐标 * * @return x */
    private int getCenterX() {
        return getPaddingLeft() + mExtRadius + mExtArcWidth / 2;
    }

    /** * 获取圆心u坐标 * * @return y */
    private int getCenterY() {
        return getPaddingTop() + mExtRadius + mExtArcWidth / 2;
    }


    private int getFontHeight(Paint paint, int textSize) {
        paint.setTextSize(textSize);
        paint.getTextBounds("j", 0, 1, mRectText);
        return mRectText.height();
    }

    private int getTextWidth(Paint paint, int textSize, String text) {
        paint.setTextSize(textSize);
        paint.getTextBounds(text, 0, text.length(), mRectText);
        return mRectText.width();
    }


    public void setValue(int insideValue, int extValue) {

        this.mInsideValue = insideValue;
        this.mText1 = insideValue + "%";
        this.mExtValue = extValue;
        this.mText3 = extValue + "%";
        startAnimation();
    }

    /** * 为进度设置动画 */
    public void startAnimation() {
        mProgressAnimator = ValueAnimator.ofFloat(0, mAngle);
        mProgressAnimator.setDuration(ANIMATOR_DURATION);
        mProgressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float angle = (float) animation.getAnimatedValue();
                mInsideCurValue = (int) ((angle / mAngle) * mInsideValue);
                mExtCurValue = (int) ((angle / mAngle) * mExtValue);
                invalidate();
            }
        });
        mProgressAnimator.start();
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }

    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                Resources.getSystem().getDisplayMetrics());
    }

}

    <declare-styleable name="DoubleArcProgressBar">
        <attr name="drpb_start_angle" format="float" />
        <attr name="drpb_angle" format="float" />
        <attr name="drpb_inside_color" format="color"/>
        <attr name="drpb_inside_progress_color" format="color"/>
        <attr name="drpb_inside_width" format="dimension"/>
        <attr name="drpb_inside_value" format="integer"/>
        <attr name="drpb_inside_max" format="integer"/>
        <attr name="drpb_inside_radius" format="dimension"/>
        <attr name="drpb_ext_color" format="color"/>
        <attr name="drpb_ext_progress_color" format="color"/>
        <attr name="drpb_ext_width" format="dimension"/>
        <attr name="drpb_ext_value" format="integer"/>
        <attr name="drpb_ext_max" format="integer"/>
        <attr name="drpb_ext_radius" format="dimension"/>
        <attr name="drpb_text1_color" format="color" />
        <attr name="drpb_text1_size" format="dimension" />
        <attr name="drpb_text1" format="string"/>
        <attr name="drpb_text2_color" format="color" />
        <attr name="drpb_text2_size" format="dimension" />
        <attr name="drpb_text2" format="string"/>
        <attr name="drpb_text3_color" format="color" />
        <attr name="drpb_text3_size" format="dimension" />
        <attr name="drpb_text3" format="string"/>
        <attr name="drpb_text4_color" format="color" />
        <attr name="drpb_text4_size" format="dimension" />
        <attr name="drpb_text4" format="string"/>
    </declare-styleable>
上一篇:Android TV 焦点移动飞框的实现 下一篇:Flexbox简介