好久都么有更新博客了,今天给大家带来一片自定义防”最右”进度条的demo,先看下效果:
自定义属性
首先在res/values文件夹下新建一个attrs.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="circle_radius" format="dimension" />
<attr name="circle_color" format="color" />
<declare-styleable name="selfProgress">
<attr name="circle_radius" />
<attr name="circle_color" />
</declare-styleable>
</resources>
可以看到这里我定义的是圆形进度条的半径和颜色。
在自定义view的构造方法中获取自定义的属性值
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//获取自定义的属性
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.selfProgress,defStyleAttr,0);
int count = array.getIndexCount();
//循环遍历所有的属性。
for (int i = 0; i < count; i++) {
int attr = array.getIndex(i);
switch (attr) {
case R.styleable.selfProgress_circle_radius:
mCircleRadius = (int) array.getDimensionPixelSize(attr,mCircleRadius);
break;
case R.styleable.selfProgress_circle_color:
mCircleColor = array.getColor(attr,Color.RED);
break;
}
}
//用完记得回收
array.recycle();
在布局中引入自定义view
新建一个类MyPro继承自View,并且在布局文件中引入该自定义MyPro.java
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:pro="http://schemas.android.com/apk/res/com.example.viewself"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<com.example.viewself.MyPro
android:layout_width="150dp"
android:layout_height="130dp"
pro:circle_color="#ff9876"
pro:circle_radius="40dp" />
</LinearLayout>
这里需要说明一点,就是如果我们需要使用自定义的属性,那么必须在声明的时候将其命名空间添加进去,如下:
xmlns:pro="http://schemas.android.com/apk/res/com.example.viewself"
这里的pro,自己随意命名即可,在命名空间的最后跟上当前包名。
MyPro.java
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class MyPro extends View {
private Paint mPaint = null;
private int mProgress = 0; //标识当前进度
private static final String TAG = "MyPro";
private int mCircleRadius = 60; //默认的圆形进度的半径
private int mCircleColor; //自定义的圆形进度的颜色
private Rect mRect = new Rect(); //用于测量当前显示字符串的宽度和高度
//如果要在布局中引入该自定义view,那么必须重写该构造方法
public MyPro(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyPro(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//初始化画笔,并设置抗锯齿
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//获取自定义的属性
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.selfProgress,defStyleAttr,0);
int count = array.getIndexCount();
//循环遍历所有的属性。
for (int i = 0; i < count; i++) {
int attr = array.getIndex(i);
switch (attr) {
case R.styleable.selfProgress_circle_radius:
mCircleRadius = (int) array.getDimensionPixelSize(attr,mCircleRadius);
break;
case R.styleable.selfProgress_circle_color:
mCircleColor = array.getColor(attr,Color.RED);
break;
}
}
//用完记得回收
array.recycle();
/**
* 创建线程,当当前进度<100的时候,每次随机添加进度,当进度大于100的时候跳出循环
*/
new Thread(){
@Override
public void run() {
while (mProgress < 100) {
mProgress += Math.random() * 8;
if (mProgress > 100) {
mProgress = 100;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
postInvalidate(); //通过重绘,不断重新调用ondraw方法
}
}
}.start();
}
public MyPro(Context context) {
this(context,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取到当前view的宽和高
int width = getWidth();
int height = getHeight();
//为画笔设置颜色,即绘制当前背景矩形的颜色
mPaint.setColor(Color.argb(40,0,0,0));
//设置画笔填充
mPaint.setStyle(Paint.Style.FILL);
//绘制圆角矩形
canvas.drawRoundRect(new RectF(0, 0, width, height),6,6,mPaint);
//设置圆形进度条的宽度
mPaint.setStrokeWidth(3);
//设置圆形进度条的颜色,这里就是获取到的自定义属性的颜色
mPaint.setColor(mCircleColor);
//设置空心
mPaint.setStyle(Paint.Style.STROKE);
//创建需要绘制扇形的矩形,该矩形用来限制扇形的绘制范围,这里由于是一个圆,所以是正方形的矩形
RectF rectF = new RectF(width/2 - mCircleRadius, height/2-mCircleRadius, width/2+mCircleRadius, height/2+mCircleRadius);
//根据当前进度,绘制扇形,第三个参数标识是否绘制实心扇形
canvas.drawArc(rectF ,0 ,Math.round(mProgress * 3.6),false,mPaint);
//设置字体大小
mPaint.setTextSize(30);
//重新设置绘制字体需要的画笔宽度
mPaint.setStrokeWidth(2);
Log.d(TAG,mProgress+"%"+"length is :"+mProgress+"%".length());
String text = mProgress+"%";
//测量字体的大小
mPaint.getTextBounds(text, 0, text.length(),mRect);
//根据测量值,在圆形进度条的中心绘制当前进度
canvas.drawText(mProgress+"%",width/2 - mRect.width()/2,height/2+mRect.height()/2 ,mPaint);
}
}
说明一下:
- 对于自定义view,一共有四个构造方法,如果需要在布局文件中引入当前的自定义view,则至少需要需要重写两个参数的构造方法,如果在自定义view中引入了自定义的属性,则至少需要重写三个参数的构造方法。
另外代码的注释比较详细,我就不做过多解释了哈,希望大家喜欢。