仿芝麻信用示例——里程表

MileCircleBar

仿芝麻信用示例——里程表

简介

这是一个仿芝麻信用示例——里程表,看下面效果图。
这里写图片描述

项目

github地址:MileCircleBar
欢迎克隆参考。

完整代码

package pers.owen.milecirclebar;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;

import java.text.DecimalFormat;

/**
 * 数据今日里程小圈圈
 */
public class ColorArcProgressBar extends View {

    private int mWidth;
    private int mHeight;
    private int diameter = 500;  //直径
    private float centerX;  //圆心X坐标
    private float centerY;  //圆心Y坐标

    private Paint allArcPaint;
    private Paint progressPaint;
    private Paint vTextPaint;
    private Paint hintPaint;
    private Paint degreePaint;
    private Paint curSpeedPaint;

    private RectF bgRect;

    private ValueAnimator progressAnimator;
    private PaintFlagsDrawFilter mDrawFilter;
    private SweepGradient sweepGradient;
    private Matrix rotateMatrix;

    private float startAngle = -85;
    private float sweepAngle = 265;
    private float currentAngle = 0;
    private float lastAngle;
    private int[] colors = new int[]{Color.GREEN, Color.YELLOW, Color.RED, Color.RED};
    private float maxValues = 60;
    private float curValues = 0;
    private float bgArcWidth = dipToPx(2);
    private float progressWidth = dipToPx(5);// 进度条的宽度,是画出来的进度条的宽度,不是初始化圆的宽度
    private float textSize = dipToPx(30);
    private float hintSize = dipToPx(12);
    private float curSpeedSize = dipToPx(12);
    private int aniSpeed = 1000;
    private float longdegree = dipToPx(13);// 长刻度条的长度
    private float shortdegree = dipToPx(5);// 短刻度条的长度
    private final int DEGREE_PROGRESS_DISTANCE = dipToPx(8);// 刻度条离外环的距离

    private String hintColor = "#ffffff";
    private String longDegreeColor = "#ffffff";
    private String shortDegreeColor = "#ffffff";
    private String bgArcColor = "#ffffff";
    private String titleString;
    private String hintString;

    private boolean isShowCurrentSpeed = true;
    private boolean isNeedTitle;
    private boolean isNeedUnit;
    private boolean isNeedDial;
    private boolean isNeedContent;

    // sweepAngle / maxValues 的值
    private float k;
    private DecimalFormat mFormat;

    public ColorArcProgressBar(Context context) {
        super(context, null);
        initView();
    }

    public ColorArcProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        initCofig(context, attrs);
        initView();
    }

    public ColorArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initCofig(context, attrs);
        initView();
    }

    /**
     * 初始化布局配置
     *
     * @param context
     * @param attrs
     */
    private void initCofig(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorArcProgressBar);
        int color1 = a.getColor(R.styleable.ColorArcProgressBar_front_color1, Color.GREEN);
        int color2 = a.getColor(R.styleable.ColorArcProgressBar_front_color2, color1);
        int color3 = a.getColor(R.styleable.ColorArcProgressBar_front_color3, color1);
        colors = new int[]{color1, color2, color3, color3};

        sweepAngle = a.getInteger(R.styleable.ColorArcProgressBar_total_engle, 270);
        bgArcWidth = a.getDimension(R.styleable.ColorArcProgressBar_back_width, dipToPx(2));
        progressWidth = a.getDimension(R.styleable.ColorArcProgressBar_front_width, dipToPx(10));
        isNeedTitle = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_title, false);
        isNeedContent = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_content, false);
        isNeedUnit = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_unit, false);
        isNeedDial = a.getBoolean(R.styleable.ColorArcProgressBar_is_need_dial, false);
        hintString = a.getString(R.styleable.ColorArcProgressBar_string_unit);
        titleString = a.getString(R.styleable.ColorArcProgressBar_string_title);
        curValues = a.getFloat(R.styleable.ColorArcProgressBar_current_value, 0);
        maxValues = a.getFloat(R.styleable.ColorArcProgressBar_max_value, 60);
        setCurrentValues(curValues);
        setMaxValues(maxValues);
        a.recycle();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = (int) (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE);
        int height = (int) (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE);
        setMeasuredDimension(width, height);
    }

    private void initView() {

//        diameter = 3 * getScreenWidth() / 5;
        diameter = dipToPx(182);
        //弧形的矩阵区域
        bgRect = new RectF();
        bgRect.top = longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE;
        bgRect.left = longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE;
        bgRect.right = diameter + (longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE);
        bgRect.bottom = diameter + (longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE);

        //圆心
        centerX = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE) / 2;
        centerY = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE) / 2;

        //外部刻度线
        degreePaint = new Paint();
        degreePaint.setColor(Color.parseColor(longDegreeColor));
        degreePaint.setStyle(Paint.Style.STROKE);

        //整个弧形
        allArcPaint = new Paint();
        allArcPaint.setAntiAlias(true);
        allArcPaint.setStyle(Paint.Style.STROKE);
        allArcPaint.setStrokeWidth(bgArcWidth);
        allArcPaint.setColor(Color.parseColor(bgArcColor));
        allArcPaint.setStrokeCap(Paint.Cap.ROUND);

        //当前进度的弧形
        progressPaint = new Paint();
        progressPaint.setAntiAlias(true);
        progressPaint.setStyle(Paint.Style.STROKE);
        progressPaint.setStrokeCap(Paint.Cap.ROUND);
        progressPaint.setStrokeWidth(dipToPx(5));
        progressPaint.setColor(Color.GREEN);

        //内容显示文字
        vTextPaint = new Paint();
        vTextPaint.setTextSize(textSize);
        vTextPaint.setColor(Color.WHITE);
        vTextPaint.setTextAlign(Paint.Align.CENTER);

        //显示单位文字
        hintPaint = new Paint();
        hintPaint.setTextSize(hintSize);
        hintPaint.setColor(Color.parseColor(hintColor));
        hintPaint.setTextAlign(Paint.Align.CENTER);

        //显示标题文字
        curSpeedPaint = new Paint();
        curSpeedPaint.setTextSize(curSpeedSize);
        curSpeedPaint.setColor(Color.parseColor(hintColor));
        curSpeedPaint.setTextAlign(Paint.Align.CENTER);

        mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        sweepGradient = new SweepGradient(centerX, centerY, colors, null);
        rotateMatrix = new Matrix();

    }

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

        if (isNeedDial) {
            //画刻度线
            drawOuterLine(canvas);
        }

        // 内钟表线
        drawInnerLine(canvas);

        // 画内圈
        drawCircle(canvas);

        //整个弧
//        canvas.drawArc(bgRect, startAngle, sweepAngle, false, allArcPaint);

        //设置渐变色
        rotateMatrix.setRotate(-90, centerX, centerY);
        sweepGradient.setLocalMatrix(rotateMatrix);
        progressPaint.setShader(sweepGradient);

        //当前进度
        canvas.drawArc(bgRect, startAngle, currentAngle, false, progressPaint);

        if (isNeedContent) {
            canvas.drawText(mFormat.format(curValues), centerX, centerY + textSize / 3, vTextPaint);
        }
        if (isNeedUnit) {
            canvas.drawText(hintString, centerX, centerY + 4 * textSize / 3, hintPaint);
        }
        if (isNeedTitle) {
            canvas.drawText(titleString, centerX, centerY - 4 * textSize / 3, curSpeedPaint);
        }

        invalidate();
    }

    /**
     * 画内圈
     *
     * @param canvas
     */
    private void drawCircle(Canvas canvas) {
        canvas.drawCircle(centerX, centerY, diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE, degreePaint);
    }

    /**
     * 画钟表线
     */
    private void drawInnerLine(Canvas canvas) {
        for (int i = 0; i < 60; i++) {
            degreePaint.setStrokeWidth(dipToPx(1));
            degreePaint.setColor(Color.parseColor(longDegreeColor));
            canvas.drawLine(centerX, centerY - diameter / 2 + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE,
                    centerX, centerY - diameter / 2 + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE - (longdegree - progressWidth / 2 - dipToPx(3)), degreePaint);
            canvas.rotate(6, centerX, centerY);
        }
    }

    /**
     * 画外部钟表线
     */
    private void drawOuterLine(Canvas canvas) {
        for (int i = 0; i < 40; i++) {
            if (i > 15 && i < 25) {
                canvas.rotate(9, centerX, centerY);
                continue;
            }
            if (i % 5 == 0) {
                degreePaint.setStrokeWidth(dipToPx(2));
                degreePaint.setColor(Color.parseColor(longDegreeColor));
                canvas.drawLine(centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE,
                        centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - longdegree, degreePaint);
            } else {
                degreePaint.setStrokeWidth(dipToPx(1.4f));
                degreePaint.setColor(Color.parseColor(shortDegreeColor));
                canvas.drawLine(centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longdegree - shortdegree) / 2,
                        centerX, centerY - diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longdegree - shortdegree) / 2 - shortdegree, degreePaint);
            }

            canvas.rotate(9, centerX, centerY);
        }
    }

    /**
     * 设置最大值
     *
     * @param maxValues
     */
    public void setMaxValues(float maxValues) {
        if (maxValues < 0.001) {
            maxValues = 0.001f;
        }
        this.maxValues = maxValues;
        k = sweepAngle / maxValues;
    }

    /**
     * 设置当前值
     *
     * @param currentValues
     */
    public void setCurrentValues(float currentValues) {
        // 小于100保留两位有效数字,小于1000保留一位,1000以上取整。
        if (currentValues < 100) {
            mFormat = new DecimalFormat("###,###,##0.00");
        } else if (currentValues < 1000){
            mFormat = new DecimalFormat("###,###,##0.0");
        } else {
            mFormat = new DecimalFormat("###,###,##0");
        }

        if (currentValues > maxValues) {
            currentValues = maxValues;
        }

        if (currentValues < 0.001) {
            currentValues = 0.001f;
        }
        this.curValues = currentValues;
        setAnimation(currentValues * k, aniSpeed);
    }

    /**
     * 设置整个圆弧宽度
     *
     * @param bgArcWidth
     */
    public void setBgArcWidth(int bgArcWidth) {
        this.bgArcWidth = bgArcWidth;
    }

    /**
     * 设置进度宽度
     *
     * @param progressWidth
     */
    public void setProgressWidth(int progressWidth) {
        this.progressWidth = progressWidth;
    }

    /**
     * 设置速度文字大小
     *
     * @param textSize
     */
    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }

    /**
     * 设置单位文字大小
     *
     * @param hintSize
     */
    public void setHintSize(int hintSize) {
        this.hintSize = hintSize;
    }

    /**
     * 设置单位文字
     *
     * @param hintString
     */
    public void setUnit(String hintString) {
        this.hintString = hintString;
        invalidate();
    }

    /**
     * 设置直径大小
     *
     * @param diameter
     */
    public void setDiameter(int diameter) {
        this.diameter = dipToPx(diameter);
    }

    /**
     * 设置标题
     *
     * @param title
     */
    public void setTitle(String title) {
        this.titleString = title;
    }

    /**
     * 设置是否显示标题
     *
     * @param isNeedTitle
     */
    private void setIsNeedTitle(boolean isNeedTitle) {
        this.isNeedTitle = isNeedTitle;
    }

    /**
     * 设置是否显示单位文字
     *
     * @param isNeedUnit
     */
    private void setIsNeedUnit(boolean isNeedUnit) {
        this.isNeedUnit = isNeedUnit;
    }

    /**
     * 设置是否显示外部刻度盘
     *
     * @param isNeedDial
     */
    private void setIsNeedDial(boolean isNeedDial) {
        this.isNeedDial = isNeedDial;
    }

    /**
     * 为进度设置动画
     * @param current
     */
    private void setAnimation(float current, int length) {
        progressAnimator = ValueAnimator.ofFloat(0, current);
        progressAnimator.setDuration(length);
        progressAnimator.setTarget(currentAngle);
        progressAnimator.addUpdateListener(animation -> {
            currentAngle = (float) animation.getAnimatedValue();
            curValues = currentAngle / k;
        });
        progressAnimator.setInterpolator(new DecelerateInterpolator());
        progressAnimator.start();
    }

    /**
     * dip 转换成px
     *
     * @param dip
     * @return
     */
    private int dipToPx(float dip) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

    /**
     * 得到屏幕宽度
     *
     * @return
     */
    private int getScreenWidth() {
        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.widthPixels;
    }
}

使用

xml中定义

<pers.owen.milecirclebar.ColorArcProgressBar
    android:layout_width="182dp"
    android:layout_height="182dp"
    android:id="@+id/bar_day"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="100dp"
    app:is_need_content="true"
    app:front_color1="#00ffffff"
    app:front_color2="#66ffffff"
    app:front_color3="#ffffffff"
    app:max_value="100"
    app:back_width="2dp"
    app:front_width="7dp"
    app:total_engle="360"
    app:is_need_unit="true"
    app:string_unit="km"
    app:is_need_title="true"
    app:string_title="今日里程"
    app:back_color="@android:color/darker_gray" />

主函数中调用

private void refreshBar() {
    switch (mFlag % 3) {
        case 0:
            mBarDay.setTitle("今日里程");
            mBarDay.setMaxValues(23);
            mBarDay.setCurrentValues(23);
            break;
        case 1:
            mBarDay.setTitle("周里程");
            mBarDay.setMaxValues(480);
            mBarDay.setCurrentValues(480);
            break;
        case 2:
            mBarDay.setTitle("总里程");
            mBarDay.setMaxValues(3600);
            mBarDay.setCurrentValues(3600);
            break;
    }
}

参考源码请点击这里

Get busy living, or get busy dying. ——《The Shawshank Redemption》

猜你喜欢

转载自blog.csdn.net/u014158743/article/details/81508431
今日推荐