说明:onDraw必须要重写,onMesure可以不重写
自定义View,实现如下图进度条
第一步:自定义View的属性
<declare-styleable name="CustomView">
<attr name="text_size" format="dimension"/>
declare-styleable>
第二步:在自定义View的构造方法中获取我们自定义的属性
1、在布局文件中添加我们的自定义View
<com.cn.liuyz.customviewdemo.CustomView
android:id="@+id/cv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:text_size="30sp"/>
2、在自定义View中获取自定义属性
public class CustomView extends View {
private int mTestSize;
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
private Paint mPaint;
private Rect mBound;
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0);
mTestSize = typedArray.getDimensionPixelOffset(R.styleable.CustomView_text_size, 0);
typedArray.recycle();
//创建画笔
mPaint = new Paint();
//抗锯齿
mPaint.setAntiAlias(true);
//设置字体大小
mPaint.setTextSize(mTestSize);
mBound = new Rect();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
.....省略.....
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
.....省略.....
}
}
第三步:重写onDraw
private String curPro ="0%";
private int progress = 0;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//设置画笔颜色
mPaint.setColor(Color.YELLOW);
//只画轮廓STROKE 边框
mPaint.setStrokeWidth(20);
mPaint.setStyle(Paint.Style.STROKE);
//画矩形
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);
float curProgress = (float) progress / 100;
curPro = progress + "%";
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(0);
//全部填充FILL
mPaint.setStyle(Paint.Style.FILL);
int current = (int) (curProgress * (getMeasuredWidth() - 10));
canvas.drawRect(10, 10, current, getMeasuredHeight()-10, mPaint);
mPaint.getTextBounds(curPro, 0, curPro.length(), mBound);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(0);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(curPro, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}
通过setProgress方法传进来进度,再通过invalidate方法刷新onDraw
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}
创建一个线程并通过Handler机制刷新进度条
private boolean isTrue = true;
private Handler handler = new Handler();
private int prograss = 0;
private void btn2Click() {
prograss = 0;
isTrue = true;
new Thread(new Runnable() {
@Override
public void run() {
while (isTrue) {
prograss++;
//休息100毫秒
SystemClock.sleep(100);
//通过Handler更新进度条
handler.post(new Runnable() {
@Override
public void run() {
mCustomView.setProgress(prograss);
}
});
if (prograss == 100) {
isTrue = false;
}
}
}
}).start();
}
重写onMesure条件
所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法:
重写之前先了解MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
curPro = progress + "%";
Log.d("liuyz:::", "onMeasure");
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY){
width = widthSize;
} else{
mPaint.getTextBounds(curPro, 0, curPro.length(), mBound);
float textWidth = mBound.width();
int wrapWidth = (int) (getPaddingLeft() + textWidth + getPaddingRight());
width = wrapWidth;
}
if (heightMode == MeasureSpec.EXACTLY){
height = heightSize;
} else{
mPaint.getTextBounds(curPro, 0, curPro.length(), mBound);
float textHeight = mBound.height();
int wrapHeight = (int) (getPaddingTop() + textHeight + getPaddingBottom());
height = wrapHeight;
}
setMeasuredDimension(width, height);
}