Android自定义圆角矩形进度条

效果图:

  或 

方法讲解:

(1)invalidate()方法

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时, 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。一般在自定义控件中会用到这个方法。

(2)RectF方法的应用

RectF是用来绘画矩形的方法。 

RectF(left,top,right,bottom),四个参数的含义分别是父控件距离矩形左上右下边距的距离,以下用图来说明:

drawRoundRect方法是用来绘制圆角矩形的,它的参数如下: 
参数说明 

rect:RectF对象。 
rx:x方向上的圆角半径。 
ry:y方向上的圆角半径。 
paint:绘制时所使用的画笔。

(3)onMeasure方法

指定自定义控件在屏幕上的大小,onMeasure方法的两个参数是由上一层控件 传入的大小,而且是模式和尺寸混合在一起的数值,需要MeasureSpec.getMode(widthMeasureSpec) 得到模式,MeasureSpec.getSize(widthMeasureSpec)得到尺寸。

onMeasure的几种模式分别为EXACTLY,AT_MOST,UNSPECIFIED。

[1]MeasureSpec.EXACTLY

MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width=”50dip”,或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

[2]MeasureSpec.AT_MOST

MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

[3]MeasureSpec.UNSPECIFIED

MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

实现步骤:

a、在values文件夹下新建attrs.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="CircleProgressBar">
        <attr name="croundColor" format="color"/>
        <attr name="croundProgressColor" format="color"/>
        <attr name="cfillColor" format="color"/>
        <attr name="croundWidth" format="dimension"></attr>
        <attr name="croundProgressWidth" format="dimension"></attr>        
        <attr name="ctextColor" format="color" />  
        <attr name="ctextSize" format="dimension" />         
        <attr name="cnumberSize" format="dimension" />        
        <attr name="cparaLable" format="string" />
        <attr name="cunitLable" format="string" />   
    </declare-styleable>

    <declare-styleable name="RoundRectProgressBar">
        <attr name="cbarRoundColor" format="color"/>
        <attr name="cbarProgressColor" format="color"/>
        <attr name="cbarFillColor" format="color"/>
        <attr name="cbarOrientation">
              <enum name="HORIZONTAL" value="0"></enum>
              <enum name="VERTICAL" value="1"></enum>
        </attr>
    </declare-styleable>
    
</resources>

b、新建RoundRectProgressBar类继承View

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * 自定义圆角矩形进度条view
 *
 * @author xl
 */
public class RoundRectProgressBar extends View {

    private final static String TAG = RoundRectProgressBar.class.getSimpleName();

    /**
     * 画笔对象的引用
     */
    private Paint paint;

    /**
     * 圆角环的颜色
     */
    private int roundColor;

    /**
     * 进度的颜色
     */
    private int fillProgressColor;

    /**
     * 填充的颜色
     */
    private int fillColor;

    /**
     * 圆角矩形宽度
     */
    private int roundWidth;

    /**
     * 圆角矩形高度
     */
    private int roundHeight;

    /**
     * 进度条方向,0水平,1垂直
     */
    private int barOrientation;

    /**
     * 进度条最大值
     */
    private float max = 100;

    /**
     * 进度条当前值
     */
    private float progress = 30;

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

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

    public RoundRectProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //获取画笔
        paint = new Paint();
        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundRectProgressBar);
        //获取自定义属性和默认值
        roundColor = mTypedArray.getColor(R.styleable.RoundRectProgressBar_cbarRoundColor, Color.RED);
        fillProgressColor = mTypedArray.getColor(R.styleable.RoundRectProgressBar_cbarProgressColor, Color.GREEN);
        fillColor = mTypedArray.getColor(R.styleable.RoundRectProgressBar_cbarFillColor, Color.BLUE);
        barOrientation = mTypedArray.getInt(R.styleable.RoundRectProgressBar_cbarOrientation, 0);
        //回收TypedArray资源
        mTypedArray.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置抗锯齿效果
        paint.setAntiAlias(true);
        //设置画笔颜色
        paint.setColor(roundColor);
        //进度方向
        if (barOrientation == 0) {
            //水平,向右
            try {
                int round = roundHeight / 2;
                //RectF:绘制矩形,四个参数分别是left,top,right,bottom,类型是单精度浮点数
                RectF rf = new RectF(0, 0, roundWidth, roundHeight);
                //绘制圆角矩形,背景色为画笔颜色
                canvas.drawRoundRect(rf, round, round, paint);
                //设置progress内部是灰色
                paint.setColor(fillColor);
                RectF rectBlackBg = new RectF(2, 2, roundWidth - 2, roundHeight - 2);
                canvas.drawRoundRect(rectBlackBg, round, round, paint);
                //设置进度条进度及颜色
                float section = progress / max;
                RectF rectProgressBg = new RectF(2, 2, (roundWidth - 2) * section, roundHeight - 2);
                if (section != 0.0f) {
                    paint.setColor(fillProgressColor);
                } else {
                    paint.setColor(Color.TRANSPARENT);
                }
                canvas.drawRoundRect(rectProgressBg, round, round, paint);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            //垂直,向上
            try {
                int round = roundWidth / 2;
                //RectF:绘制矩形,四个参数分别是left,top,right,bottom,类型是单精度浮点数
                RectF rf = new RectF(0, 0, roundWidth, roundHeight);
                //绘制圆角矩形,背景色为画笔颜色
                canvas.drawRoundRect(rf, round, round, paint);
                //设置progress内部是灰色
                paint.setColor(fillColor);
                RectF rectBlackBg = new RectF(2, 2, roundWidth - 2, roundHeight - 2);
                canvas.drawRoundRect(rectBlackBg, round, round, paint);
                //设置进度条进度及颜色
                float section = progress / max;
                RectF rectProgressBg = new RectF(2, roundHeight - 2 - (roundHeight - 4) * section, roundWidth - 2, roundHeight - 2);
                if (section != 0.0f) {
                    paint.setColor(fillProgressColor);
                } else {
                    paint.setColor(Color.TRANSPARENT);
                }
                canvas.drawRoundRect(rectProgressBg, round, round, paint);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * dip转px
     *
     * @param dip
     * @return
     */
    private int dipToPx(int dip) {
        float scale = getContext().getResources().getDisplayMetrics().density;
        //加0.5是为了四舍五入
        return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
    }

    /**
     * 指定自定义控件在屏幕上的大小,onMeasure方法的两个参数是由上一层控件
     * 传入的大小,而且是模式和尺寸混合在一起的数值,需要MeasureSpec.getMode(widthMeasureSpec)
     * 得到模式,MeasureSpec.getSize(widthMeasureSpec)得到尺寸
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        //MeasureSpec.EXACTLY,精确尺寸
        if (widthSpecMode == MeasureSpec.EXACTLY || widthSpecMode == MeasureSpec.AT_MOST) {
            roundWidth = widthSpecSize;
        } else {
            roundWidth = 0;
        }
        if (heightSpecMode == MeasureSpec.EXACTLY || heightSpecMode == MeasureSpec.AT_MOST) {
            roundHeight = heightSpecSize;
        } else {
            roundHeight = 0;
        }
        //MeasureSpec.AT_MOST,最大尺寸,只要不超过父控件允许的最大尺寸即可,MeasureSpec.UNSPECIFIED未指定尺寸
        //if (heightSpecMode == MeasureSpec.AT_MOST || heightSpecMode == MeasureSpec.UNSPECIFIED) {
        //    roundHeight = dipToPx(20);
        //} else {
        //    roundHeight = heightSpecSize;
        //}
        //设置控件实际大小
        setMeasuredDimension(roundWidth, roundHeight);
    }


    /**
     * 设置进度
     *
     * @param progress
     */
    public synchronized void setProgress(float progress) {
        if (progress < 0) {
            throw new IllegalArgumentException("value can not be negative");
        }
        if (progress > max) {
            this.progress = max;
        } else {
            this.progress = progress;
        }
        postInvalidate();
    }

    /**
     * 设置最大值
     *
     * @param max
     */
    public synchronized void setMax(float max) {
        if (max < 0) {
            throw new IllegalArgumentException("value can not be negative");
        }
        this.max = max;
    }

}

c、布局文件中引用activity_main.xml

<ups.invt.com.view.RoundRectProgressBar
                            android:id="@+id/bar"
                            android:layout_width="20dp"
                            android:layout_height="100dp"
                            android_custom:cbarRoundColor="@color/transparent"
                            android_custom:cbarFillColor="@color/white"
                            android_custom:cbarProgressColor="@color/bar_fill_color"
                            android_custom:cbarOrientation="VERTICAL"
                            android:layout_centerInParent="true"/>

d、MainActivity.java中设置进度

progress = (RoundRectProgressBar) findViewById(R.id.bar);
progress.setMax(100);

progress.setProgress(80);

完!!!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值