ITPub博客

首页 > IT职业 > IT图书 > Android弧形ProgressBar、SeekBar

Android弧形ProgressBar、SeekBar

IT图书 作者:germo 时间:2021-09-09 09:41:25 0 删除 编辑

网上有很多弧形或者圆形的ProgressBar和SeekBar。前几天无意中发现一个弧形的ProgressBar觉得挺不错的,就下载来看看源码。

运行他的Demo的时候发现几个问题,并且有些问题在issue里面也有人提出了,但是作者一直没有回复,我把问题修复之后加上了Seek的功能,让它能当做SeekBar用。

原作者的Demo效果图

图片描述


存在的问题:

  1. 不能通过XML配置控件的大小,源码里面写死了,写成占屏幕的百分比。

  2. 有几个属性的颜色值设置无效。比如默认的弧形背景色

  3. 放大缩小控件之后对应的字体没有相应的调整大小

需要考虑的问题点:

我们从最下面带刻度带提示的效果图入手

####我们呢先分析原作者的代码:

package com.shinelw.colorarcprogressbar;import android.animation.ValueAnimator;import android.content.Context;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;/**
 * colorful arc progress bar
 * Created by shinelw on 12/4/15.
 */public class ColorArcProgressBar extends View{

    private int mWidth;    private int mHeight;    //直径
    private int diameter = 500;    private RectF bgRect;    //圆心
    private float centerX;    private float centerY;    private Paint allArcPaint;    private Paint progressPaint;    private Paint vTextPaint;    private Paint hintPaint;    private Paint degreePaint;    private Paint curSpeedPaint;    private float startAngle = 135;    private float sweepAngle = 270;    private float currentAngle = 0;    private float lastAngle;    private int[] colors = {Color.GREEN, Color.YELLOW, Color.RED, Color.RED};    private ValueAnimator progressAnimator;    private float maxValues = 60;    private float curValues = 0;    private int bgArcWidth = dipToPx(2);    private int progressWidth = dipToPx(10);    private int textSize = dipToPx(80);    private int hintSize = dipToPx(22);    private int curSpeedSize = dipToPx(13);    private int aniSpeed = 1000;    private int longdegree = dipToPx(13);    private int shortdegree = dipToPx(5);    private final int DEGREE_PROGRESS_DISTANCE = dipToPx(8);    private String hintColor = "#676767";    private String longDegreeColor = "#d2d2d2";    private String shortDegreeColor = "#adadad";    private String bgArcColor = "#111111";    private boolean isShowCurrentSpeed = true;    private String hintString = "Km/h";    // sweepAngle / maxValues 的值
    private float k;    public ColorArcProgressBar(Context context) {        super(context);
        initView();
    }    public ColorArcProgressBar(Context context, AttributeSet attrs) {        super(context, attrs);
        initView();
    }    public ColorArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);
        initView();
    }    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int width = 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE;        int height= 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.setColor(Color.parseColor(longDegreeColor));        //整个弧形
        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(progressWidth);
        progressPaint.setColor(Color.GREEN);        //当前速度显示文字
        vTextPaint = new Paint();
        vTextPaint.setTextSize(textSize);
        vTextPaint.setColor(Color.WHITE);
        vTextPaint.setTextAlign(Paint.Align.CENTER);        //显示“km/h”文字
        hintPaint = new Paint();
        hintPaint.setTextSize(hintSize);
        hintPaint.setColor(Color.parseColor(hintColor));
        hintPaint.setTextAlign(Paint.Align.CENTER);        //显示“km/h”文字
        curSpeedPaint = new Paint();
        curSpeedPaint.setTextSize(curSpeedSize);
        curSpeedPaint.setColor(Color.parseColor(hintColor));
        curSpeedPaint.setTextAlign(Paint.Align.CENTER);



    }    @Override
    protected void onDraw(Canvas canvas) {        //抗锯齿
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));        //画刻度线
        for (int i = 0; i  15 && i  maxValues) {
            currentValues = maxValues;
        }        if (currentValues = 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;
    }    public void setIsShowCurrentSpeed(boolean isShowCurrentSpeed) {        this.isShowCurrentSpeed = isShowCurrentSpeed;
    }    /**
     * 初始加载页面时设置加载动画
     */
    public void setDefaultWithAnimator() {
        setAnimation(sweepAngle, currentAngle, 2000);
    }



}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321

从以上代码可以看出:

  • 在initView 的时候设置了弧形的直径diameter = 3 * getScreenWidth() / 5;也就是弧形的直径是根据屏幕的大小定的。 
    我们再看OnMeasure方法

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

所以我们知道:不管你怎么设置控件的宽高,都没有效果。这是第一个问题

  • 设置某些颜色值无效的问题: 
    颜色值的设置是通常作用于画笔上,我们先看看几个画笔:

        private Paint allArcPaint;//背景弧形的画笔(圆弧)
        private Paint progressPaint;//进度画笔(当前速度)
        private Paint vTextPaint;//内容文字画笔(80)
        private Paint hintPaint;//单位文字画笔(km/h)
        private Paint degreePaint;//刻度画笔(刻度条)
        private Paint curSpeedPaint;//标题文字画笔(当前速度)

这些画笔的颜色值在initView的时候初始化,但是颜色值并没有在initConfig的时候取出属性值并且配置,所以这是导致设置颜色无效的原因

注意:给画笔设置的颜色值必须带有透明度,不然会自动带上全透明效果。看不到任何信息

  • 调整控件大小的时候圆弧内的文字没有做出大小和位置的调整 
    在源代码中,initView的时候就已经设置TextSize了,而initView是在实例化的时候调用的,这时候控件的大小都还没有确定,所以需要把和大小相关的值都放到OnSizeChange中,或者在OnMeasure中获取控件的实际大小之后再初始化这些值

    @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh)
        {            super.onSizeChanged(w, h, oldw, oldh);
            mWidth = w;
            mHeight = h;
            Log.v("ColorArcProgressBar", "onSizeChanged: mWidth:" + mWidth + " mHeight:" + mHeight);

            diameter = (int) (Math.min(mWidth, mHeight) - 2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2));

            Log.v("ColorArcProgressBar", "onSizeChanged: diameter:" + diameter);            //弧形的矩阵区域
            bgRect = new RectF();
            bgRect.top = longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2;
            bgRect.left = longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2;
            bgRect.right = diameter + (longDegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE);
            bgRect.bottom = diameter + (longDegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE);

            Log.v("ColorArcProgressBar", "initView: " + diameter);            //圆心
            centerX = (2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2) + diameter) / 2;
            centerY = (2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2) + diameter) / 2;

            sweepGradient = new SweepGradient(centerX, centerY, colors, null);

            mTouchInvalidateRadius = Math.max(mWidth, mHeight) / 2 - longDegree - DEGREE_PROGRESS_DISTANCE - progressWidth * 2;            if(isAutoTextSize)
            {
                textSize = (float) (diameter * 0.3);
                hintSize = (float) (diameter * 0.1);
                curSpeedSize = (float) (diameter * 0.1);

                vTextPaint.setTextSize(textSize);
                hintPaint.setTextSize(hintSize);
                curSpeedPaint.setTextSize(curSpeedSize);
            }

        }

通过在OnSizeChange中初始化这些动态的尺寸,就解决了文字缩放的问题。


http://www.apkbus.com/thread-601879-1-1.html

原文链接:http://www.apkbus.com/blog-865069-78319.html

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1868/viewspace-2806089/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-07-17

  • 博文量
    209
  • 访问量
    8226