Android自定义View, 安全中心安全指数进度条,圆弧进度条

来源:互联网 发布:java五子棋视频教程 编辑:程序博客网 时间:2024/06/08 10:01

最近新提出需求, 需要自定义一个安全中心页面,表示安全分数的自定义progressbar.效果在最下方贴图.

下面来说下具体的实现方法:

public class ColorArcProgressBar extends View {    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 = 155;    private float sweepAngle = 230;    private float currentAngle = 0.01f;    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(10);    private float progressWidth = dipToPx(10);    private float textSize = dipToPx(50);    private float hintSize = dipToPx(9);    private float curSpeedSize = dipToPx(9);    private int aniSpeed = 1500;    private float longDegree = dipToPx(13);    private float shortDegree = dipToPx(5);    private final int DEGREE_PROGRESS_DISTANCE = dipToPx(1);    private String hintColor = "#8d9298";    private String bgArcColor = "#F0F0F0";    private String titleString;    private String hintString;    private boolean isNeedTitle;    private boolean isNeedUnit;    private boolean isNeedDial;    private boolean isNeedContent;    private boolean isNeedProgress = false;    // sweepAngle / maxValues 的值    private float k;    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();    }    /**     * 初始化布局配置     */    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);        int color4 = a.getColor(R.styleable.ColorArcProgressBar_front_color4, color1);        int color5 = a.getColor(R.styleable.ColorArcProgressBar_front_color5, color1);        colors = new int[]{color1, color2, color3, color4, color5, color5};        sweepAngle = a.getInteger(R.styleable.ColorArcProgressBar_total_engle, 230);        bgArcWidth = a.getDimension(R.styleable.ColorArcProgressBar_back_width, dipToPx(10));        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;        //弧形的矩阵区域        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.setAntiAlias(true);        degreePaint.setColor(Color.parseColor("#C8C8C8"));        degreePaint.setStrokeWidth(dipToPx(1f));        degreePaint.setTextSize(dipToPx(10f));        //整个弧形        allArcPaint = new Paint();        allArcPaint.setAntiAlias(true);        allArcPaint.setStyle(Paint.Style.STROKE);        allArcPaint.setStrokeCap(Paint.Cap.ROUND);        allArcPaint.setStrokeWidth(bgArcWidth);        allArcPaint.setColor(Color.parseColor(bgArcColor));        //当前进度的弧形        progressPaint = new Paint();        progressPaint.setAntiAlias(true);        progressPaint.setStyle(Paint.Style.STROKE);        progressPaint.setStrokeCap(Paint.Cap.ROUND);        progressPaint.setStrokeWidth(progressWidth);        progressPaint.setColor(Color.GREEN);        //内容显示文字        vTextPaint = new Paint();        vTextPaint.setTextSize(textSize);        vTextPaint.setColor(Color.BLACK);        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.WHITE);        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) {            //画刻度线 TODO 画刻度线可以优化            for (int i = 0; i < 156; i++) {                if (i < 28 || i > 128) {                    canvas.rotate(2.30769f, centerX, centerY);                    continue;                }                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);                if (((i - 28) % 20) == 0) {                    if (i == 128) {                        canvas.rotate(-2.30769f * 2, centerX, centerY);                    } else {                        canvas.rotate(-2.30769f, centerX, centerY);                    }                    canvas.rotate(180f, centerX, centerY + diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longDegree - shortDegree) / 2 - shortDegree - dipToPx(10));                    canvas.drawText(String.valueOf(i - 28), centerX, centerY + diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longDegree - shortDegree) / 2 - shortDegree - dipToPx(10), degreePaint);                    canvas.rotate(-180f, centerX, centerY + diameter / 2 - progressWidth / 2 - DEGREE_PROGRESS_DISTANCE - (longDegree - shortDegree) / 2 - shortDegree - dipToPx(10));                    if (i == 128) {                        canvas.rotate(2.30769f * 2, centerX, centerY);                    } else {                        canvas.rotate(2.30769f, centerX, centerY);                    }                }                canvas.rotate(2.30769f, centerX, centerY);            }        }        //整个弧        canvas.drawArc(bgRect, startAngle, sweepAngle, false, allArcPaint);        //设置渐变色        rotateMatrix.setRotate(150, centerX, centerY);        sweepGradient.setLocalMatrix(rotateMatrix);        progressPaint.setShader(sweepGradient);        //当前进度        if (isNeedProgress) {            canvas.drawArc(bgRect, startAngle, currentAngle, false, progressPaint);        }        if (isNeedContent) {            canvas.drawText(String.format("%.0f", curValues), centerX, centerY, vTextPaint);        }        if (isNeedUnit) {            canvas.drawText(hintString, centerX, centerY + textSize / 2.6f, hintPaint);        }        if (isNeedTitle) {            RectF rectF = new RectF();            rectF.left = centerX - dipToPx(32);            rectF.top = centerY + textSize / 1.1f - dipToPx(11);            rectF.right = centerX + dipToPx(32);            rectF.bottom = centerY + textSize / 1.1f + dipToPx(4);            canvas.drawRoundRect(rectF, dipToPx(15), dipToPx(15), vTextPaint);        //绘制圆角矩形            canvas.drawText(titleString, centerX, centerY + textSize / 1.1f, curSpeedPaint);        }        invalidate();    }    /**     * 设置最大值     */    public void setMaxValues(float maxValues) {        this.maxValues = maxValues;        k = sweepAngle / maxValues;    }    /**     * 设置当前值     */    public void setCurrentValues(float currentValues) {        if (currentValues > maxValues) {            currentValues = maxValues;        }        if (currentValues < 0) {            currentValues = 0;        }        this.curValues = currentValues;        lastAngle = currentAngle;        setAnimation(lastAngle, currentValues * k, aniSpeed);    }    /**     * 设置整个圆弧宽度     */    public void setBgArcWidth(int bgArcWidth) {        this.bgArcWidth = bgArcWidth;    }    /**     * 设置进度宽度     */    public void setProgressWidth(int progressWidth) {        this.progressWidth = progressWidth;    }    /**     * 设置速度文字大小     */    public void setTextSize(int textSize) {        this.textSize = textSize;    }    /**     * 设置单位文字大小     */    public void setHintSize(int hintSize) {        this.hintSize = hintSize;    }    public void setNeedProgress(boolean needProgress) {        isNeedProgress = needProgress;    }    /**     * 设置单位文字     */    public void setUnit(String hintString) {        this.hintString = hintString;        invalidate();    }    /**     * 设置直径大小     */    public void setDiameter(int diameter) {        this.diameter = dipToPx(diameter);    }    /**     * 设置标题     */    private void setTitle(String title) {        this.titleString = title;    }    /**     * 设置是否显示标题     */    private void setIsNeedTitle(boolean isNeedTitle) {        this.isNeedTitle = isNeedTitle;    }    /**     * 设置是否显示单位文字     */    private void setIsNeedUnit(boolean isNeedUnit) {        this.isNeedUnit = isNeedUnit;    }    /**     * 设置是否显示外部刻度盘     */    private void setIsNeedDial(boolean isNeedDial) {        this.isNeedDial = isNeedDial;    }    /**     * 为进度设置动画     */    private void setAnimation(final float last, final float current, int length) {        progressAnimator = ValueAnimator.ofFloat(last, current);        progressAnimator.setDuration(length);        progressAnimator.setTarget(currentAngle);        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                currentAngle = (float) animation.getAnimatedValue();                curValues = currentAngle / k;                if (vTextPaint != null) {                    if (0 <= curValues && curValues < 20f) {                        vTextPaint.setColor(Color.parseColor("#FB8301"));                        titleString = "安全等级低";                    } else if (20f <= curValues && curValues < 40f) {                        vTextPaint.setColor(Color.parseColor("#FBB004"));                        titleString = "安全等级低";                    } else if (40f <= curValues && curValues < 60f) {                        vTextPaint.setColor(Color.parseColor("#C9C730"));                        titleString = "安全等级中";                    } else if (60f <= curValues && curValues < 80f) {                        vTextPaint.setColor(Color.parseColor("#71CC80"));                        titleString = "安全等级中";                    } else {                        vTextPaint.setColor(Color.parseColor("#0598F6"));                        titleString = "安全等级高";                    }                }            }        });        progressAnimator.start();    }    /**     * dip 转换成px     */    private int dipToPx(float dip) {        float density = getContext().getResources().getDisplayMetrics().density;        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));    }    /**     * 得到屏幕宽度     */    private int getScreenWidth() {        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics displayMetrics = new DisplayMetrics();        windowManager.getDefaultDisplay().getMetrics(displayMetrics);        return displayMetrics.widthPixels;    }}

1.其中再为进度设置动画时,需改变安全等级背景颜色方法较笨, 应该能进一步实现背景颜色随进度条走到的颜色变而变化, 知道的小伙伴,可以在评论中给出答案噢~感谢~
2.在刚开始currentAngle 设置为0.01f,是为了适配oppo手机开始会显示进度条100%的闪烁, 改成0.01f就不会有这种bug了.属于笨方法解决哦~

贴出sttr.xml文件:

 <declare-styleable name="ColorArcProgressBar">        <attr name="back_color" format="color"/>        <attr name="front_color1" format="color"/>        <attr name="front_color2" format="color"/>        <attr name="front_color3" format="color"/>        <attr name="front_color4" format="color"/>        <attr name="front_color5" format="color"/>        <attr name="back_width" format="dimension"/>        <attr name="front_width" format="dimension"/>        <attr name="is_need_title" format="boolean"/>        <attr name="is_need_content" format="boolean"/>        <attr name="is_need_unit" format="boolean"/>        <attr name="is_need_dial" format="boolean"/>        <attr name="string_title" format="string"/>        <attr name="string_unit" format="string"/>        <attr name="total_engle" format="integer"/>        <attr name="current_value" format="float"/>        <attr name="max_value" format="float"/>    </declare-styleable>

在xml中使用:

 <com.clwapp.hx.widget.ColorArcProgressBar                    android:id="@id/color_arc_progressbar"                    android:layout_width="200dp"                    android:layout_height="200dp"                    android:layout_centerHorizontal="true"                    android:layout_marginTop="@dimen/common_13dp"                    app:back_color="@android:color/darker_gray"                    app:back_width="10dp"                    app:front_color1="#FB7E00"                    app:front_color2="#FAC405"                    app:front_color3="#73CC7C"                    app:front_color4="#06A2F3"                    app:front_color5="#0079FC"                    app:front_width="10dp"                    app:is_need_content="true"                    app:is_need_dial="true"                    app:is_need_title="true"                    app:is_need_unit="true"                    app:max_value="100"                    app:string_title="安全等级低"                    app:string_unit="BETA"                    app:total_engle="230" />

在Activity中使用:

progressBar.setNeedProgress(true);progressBar.setCurrentValues(80);

这样, 自定义progressbar就写完了, 有不足的地方,还请各大神门指正!!!

效果如图:
这里写图片描述

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 8个月婴儿37.5度怎么办 5个月宝宝38度怎么办 5个月宝宝发烧怎么办 五个月小孩38度怎么办 宝宝3岁还不会说话 怎么办 两岁宝宝流口水厉害怎么办 两周宝宝不说话怎么办 两岁宝宝说话有点口吃怎么办 一周岁的宝宝脾气不好怎么办 九个月的宝宝脾气不好怎么办 两岁宝宝脾气不好怎么办 2岁宝宝脾气不好怎么办 3岁宝宝脾气不好怎么办 脾气不好吓到宝宝了怎么办 四个月宝宝脾气不好怎么办 5岁说话不清楚该怎么办 小孩快上幼儿园了不怎么说话怎么办 四岁宝宝吐字不清楚怎么办 孕28周胎儿腿短怎么办 b超显示腿短怎么办 2岁多宝宝不愿意说话怎么办 6岁儿童咬字不清怎么办 两岁宝宝爱看电视怎么办 两岁宝宝喜欢看电视怎么办 三岁宝宝说话不清晰怎么办 儿子快四岁了说话不清楚怎么办 儿子快三岁了说话不清楚怎么办 2岁宝宝受刺激了怎么办 一岁的宝宝口臭怎么办 古话说小孩牙齿掉了怎么办 宝宝三岁胆子小怎么办 小宝宝就是不愿意学说话怎么办 2岁宝宝体重偏重怎么办 三岁宝宝体重偏重怎么办 3岁宝宝说话晚怎么办 孩子吃饭总说话吃饭慢怎么办 我的孩子不聪明怎么办 小孩个子长不高怎么办 晚修自己老喜欢讲话怎么办 宝2岁宝脾气大怎么办 宝宝比同龄孩子发育晚怎么办