自定义圆形进度条

进度条的样式有很多,大部分能够满足我们的需求,但是,不排除一些特别情况,比如:这个进度条太难看,换成这种这种..巴拉巴拉小魔仙什么的,所以,有时候就需要我们自己来处理了。

自定义动画,没什么好说的,重写View

/**
 * 圆形动画
 * Created by IKL on 2018/6/6.
 */

public class RoundProgressBar extends View {
    /**
     * 圆环半径
     */
    private int mRadius = 93; // Diameter英文为直径,该常量表示小圆直径的dp值
    /**
     * 圆环的宽度
     */
    private int mTrokeWidth = 40;
    /**
     * 起始角度
     */
    private int mStartAngle = 270;
    /**
     * 进度条进度颜色
     */
    private int mArcColor;

    private Paint mPaint;
    private int mProgress;// 表示进度
    private RectF mRect;
    private int mDiameter; // Diameter英文为直径,在该View中要绘制圆环,圆环由两个圆形确定(大圆和小圆),这个整形值表示小圆直径。
    private int mWidth;// 这个值表示圆环的宽度的2倍(大圆直径-小圆直径)

    private final int defaultColor; // 进度条背景颜色

    public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        defaultColor = Color.TRANSPARENT;
        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcProgressbar, defStyle, 0);
        int num = ta.getIndexCount();
        for (int i = 0; i < num; i++) {
            int attr = ta.getIndex(i);
            switch (attr) {
                case R.styleable.ArcProgressbar_startAngle:
                    mStartAngle = ta.getInt(attr, 135);
                    break;
                case R.styleable.ArcProgressbar_arcColor:
                    mArcColor = ta.getColor(attr, Color.parseColor("#eed306"));
                    break;
                case R.styleable.ArcProgressbar_trokeWidth:
                    mTrokeWidth = ta.getInt(attr, 15);
                    break;
            }
        }
        init();
    }

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

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

    private void init() {
        Resources res = getResources();
        // getDisplayMetrics()返回当前展示的metrics.
        DisplayMetrics metrics = res.getDisplayMetrics();
        // TypedValue.applyDimension(int unit, float value, DisplayMetrics
        // metrics)
        // 该方法中unit表示要转换成的单位,value表示数值,metrics表示当前的度量方式
        // DIAMETER是常量0x1E,十进制为30,下面语句就表示tmp的值为30dp换算成的像素数值
        float tmp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mRadius, metrics);
        // ceil函数表示向上取整
        mDiameter = (int) Math.ceil(tmp);
        tmp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mTrokeWidth, metrics);
        mWidth = (int) Math.ceil(tmp);
        Paint p = new Paint();
        p.setStyle(Paint.Style.STROKE);
        p.setAntiAlias(true);
        // setStrokeWidth()设置画笔宽度
        // p.setStrokeWidth(0.5F*mWidth+0.5F*mDiameter);
        p.setStrokeWidth(0.4F * mWidth);
        p.setStrokeCap(Paint.Cap.SQUARE);//直角进度条
        p.setColor(defaultColor);
        mPaint = p;

        float rightTop = (float) (mWidth / 2.0);// 这个值就是圆环宽度(大圆半径-小圆半径)
        mRect = new RectF(rightTop, rightTop, mDiameter + rightTop, mDiameter + rightTop);
        mProgress = 0;
    }

    protected boolean clear = false;

    @Override
    protected void onDraw(Canvas canvas) {
        // super.onDraw(canvas);

        // 如果mProgress<360,则圆形进度条还未旋转完成,则用0x7f的透明度绘制一个完整的圆形作为进度条背景
        // 注意要先绘制背景条,再绘制进度条,因为后绘制的会覆盖在先绘制的上面
        /*
         * if (mProgress < 360) { paint.setAlpha(0x7f);
         * paint.setColor(defaultColor); canvas.drawArc(mRect, 135, 270, false,
         * paint); }
         */
        if (clear) {
            mPaint.setColor(Color.TRANSPARENT);
            clear = false;
            return;
        }
        if (mProgress != 0) {
            Paint paint = mPaint;
            paint.setColor(mArcColor);
            float degree = 360.0f * mProgress / 360;
            paint.setAlpha(0xff);
            paint.setColor(mArcColor);
            canvas.drawArc(mRect, mStartAngle, degree, false, paint);
        }
    }

    @Override
    protected final void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // mDiameter表示小圆直径,mWidth表示圆环宽度的2倍,所以meas表示大圆直径
        // 所以View的hight,width都为meas
        final int meas = mDiameter + mWidth;
        setMeasuredDimension(meas, meas);
    }

    public void setProgress(int p) {
        mProgress = p;
        invalidate();
    }

    public void postProgress(final int p) {
        post(new Runnable() {
            @Override
            public void run() {
                setProgress(p);
            }
        });
    }

    public void setmArcColor(int mArcColor) {
        this.mArcColor = mArcColor;
    }

    public void reset() {
        clear = true;
        invalidate();
        mProgress = 0;
    }

    public void setGrade(final RoundProgressBar arcProgressbar, final TextView tv_grade, final int g) {
        mProgress = 1;
        arcProgressbar.reset();
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
//                if (0 < (mProgress / 3.6) && (mProgress / 3.6) <= 59) {
//                    arcProgressbar.setmArcColor(Color.parseColor("#ff0000"));
//                    tv_grade.setTextColor(Color.parseColor("#ff0000"));
//                } else if (60 < (mProgress / 3.6) && (mProgress / 3.6) <= 79) {
//                    arcProgressbar.setmArcColor(Color.parseColor("#f39700"));
//                    tv_grade.setTextColor(Color.parseColor("#f39700"));
//                } else if (80 < (mProgress / 3.6) && (mProgress / 3.6) <= 100) {
//                    arcProgressbar.setmArcColor(Color.parseColor("#42ae7c"));
//                    tv_grade.setTextColor(Color.parseColor("#42ae7c"));
//                }
                arcProgressbar.setmArcColor(Color.parseColor("#ffffff"));
                tv_grade.setTextColor(Color.parseColor("#000000"));
                if (msg.what == 0x1223) {
                    arcProgressbar.setProgress(mProgress * (1));
                    tv_grade.setText((int) (mProgress / 3.6)+"%");
                } else if (msg.what == 0x1224) {
                    tv_grade.setText(g+"%");
                }
            }
        };
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = new Message();
                if (mProgress < (int) (((float) 360 / 100) * g)) {
                    msg.what = 0x1223;
                    mProgress++;
                } else {
                    msg.what = 0x1224;
                    this.cancel();
                }
                handler.sendMessage(msg);
            }
        }, 0, 5);
    }
}

里面的一些设置:


<!--首页顶部进度条格式-->
<declare-styleable name="ArcProgressbar">
    <!-- 圆环起始角度-->
    <attr name="startAngle" format="integer" />
    <!-- 圆环的宽度  默认115-->
    <attr name="trokeWidth" format="integer" />
    <!-- 进度条进度颜色 -->
    <attr name="arcColor" format="color" />
</declare-styleable>

颜色,可以通过设置drawble文件中设置xml的方式来进行。

背景色

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="@color/blue_grey"></solid>

</shape>

样式

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:useLevel="false">

    <stroke
        android:width= "16px"
        android:color= "@color/dark_blue" />

</shape>

进度条颜色

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="@color/light_white"></solid>

</shape>

样式:


布局:

<!--圆形进度条动画-->
<RelativeLayout
    android:layout_width="350px"
    android:layout_height="350px"
    android:layout_marginTop="50px">

  <ImageView
      android:layout_width="310px"
      android:layout_height="310px"
      android:background="@drawable/blue_grey_round_shape"
      android:layout_centerInParent="true"/>

  <qnkj.cn.lianxiapp.RoundProgressBar
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/roundProgress"
      android:layout_centerInParent="true"/>

  <ImageView
      android:layout_width="138px"
      android:layout_height="138px"
      android:background="@drawable/dark_blue_ring"
      android:layout_centerInParent="true"></ImageView>

  <TextView
      android:layout_width="104px"
      android:layout_height="104px"
      android:id="@+id/tv_value"
      android:layout_centerInParent="true"
      android:gravity="center"
      android:text="0%"
      android:textSize="@dimen/thirty_two"
      android:background="@drawable/white_round"/>


</RelativeLayout>

使用:

 //圆形进度条   
   TextView tvValue=findViewById(R.id.tv_value);
RoundProgressBar RoundProgressBar= findViewById(R.id.roundProgress);
 RoundProgressBar.setProgress(56);
 //自定义view,内部显示文字的view,数字是进度
 RoundProgressBar.setGrade(RoundProgressBar, tvValue, 56);
布局有些乱,凑活着看吧。是在不行,复制粘贴下来代码也能用(没问题的话)










猜你喜欢

转载自blog.csdn.net/liu_ser/article/details/80591347