先来复习一下自定义View的步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
[ 3、重写onMesure ]
4、重写onDraw
1、自定义View的属性, 在attrs.xml里面定义我们的属性和声明我们的整个样式。
<declare-styleable name="RoundProgressBar">
<!-- 圆环的颜色 -->
<attr name="roundColor" format="color" />
<!-- 圆环进度的颜色 -->
<attr name="roundProgressColor" format="color" />
<!-- 中间进度百分比的字符串的颜色 -->
<attr name="progresstextColor" format="color" />
<!-- 中间进度百分比的字符串的字体大小 -->
<attr name="progresstextSize" format="dimension" />
<!-- 圆环的宽度 -->
<attr name="roundWidth" format="dimension" />
<!-- 最大进度 -->
<attr name="max" format="integer" />
<!-- 当前进度 -->
<attr name="progress" format="integer" />
<!-- 是否显示中间的进度 字符串-->
<attr name="textIsDisplayable" format="boolean" />
<!-- 进度的风格,实心或者空心 -->
<attr name="style">
<enum name="STOKE" value="0" />
<enum name="FILL" value="1" />
</attr>
</declare-styleable>
我们定义了9个属性,format是值该属性的取值类型:
然后在布局中声明我们的自定义View
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.pepe.widgetdemo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- 第一个取默认值 -->
<com.pepe.widgetdemo.TwoRoundProgressBar
android:layout_width="100dp"
android:layout_height="100dp" />
<com.pepe.widgetdemo.TwoRoundProgressBar
custom:style="STOKE"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginTop="10dp"
custom:max="200"
custom:progress="100"
custom:progresstextColor="#ff0000"
custom:progresstextSize="20sp"
custom:roundColor="#00ff00"
custom:roundProgressColor="#0000ff"
custom:roundWidth="15dp"
custom:textIsDisplayable="true" />
</LinearLayout>
2、在View的构造方法中,获得我们的自定义的样式
public class TwoRoundProgressBar extends View {
/**
* 圆环的颜色
*/
private int mRoundColor;
/**
* 圆环进度的颜色
*/
private int mRoundProgressColor;
/**
* 中间进度百分比的字符串的颜色
*/
private int mProgressTextColor;
/**
* 中间进度百分比的字符串的字体大小
*/
private int mProgressTextSize;
/**
* 圆环的宽度
*/
private int mRoundWidth;
/**
* 最大进度
*/
private int mMax;
/**
* 当前进度
*/
private int progress;
/**
* 是否显示中间的进度字符串
*/
private boolean mTextIsDisplayable;
/**
* 进度的风格,实心或者空心
*/
private int style;
public static final int STROKE = 0;
public static final int FILL = 1;
/**
* 画笔
*/
private Paint mPaint;
public TwoRoundProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.RoundProgressBar);
mRoundColor = typedArray.getColor(
R.styleable.RoundProgressBar_roundColor, Color.YELLOW);
mRoundProgressColor = typedArray.getColor(
R.styleable.RoundProgressBar_roundProgressColor, Color.RED);
mProgressTextColor = typedArray.getColor(
R.styleable.RoundProgressBar_progresstextColor, Color.GREEN);
mProgressTextSize = typedArray.getDimensionPixelSize(
R.styleable.RoundProgressBar_progresstextSize, 15);
mRoundWidth = typedArray.getDimensionPixelSize(
R.styleable.RoundProgressBar_roundWidth, 5);
progress = typedArray.getInteger(R.styleable.RoundProgressBar_progress, 33);
mMax = typedArray.getInteger(R.styleable.RoundProgressBar_max, 100);
mTextIsDisplayable = typedArray.getBoolean(
R.styleable.RoundProgressBar_textIsDisplayable, false);
style = typedArray.getInt(R.styleable.RoundProgressBar_style, 1);//默认实心
typedArray.recycle();
mPaint = new Paint();
}
}
我们还是重写两个参数的构造方法,我们在构造方法中获得自定义属性。
3、我们重写onDraw,onMesure调用系统提供的:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
/**
* 画最外层的大圆环
*/
int centre = getWidth() / 2; // 获取圆心的x坐标
int radius = (int) (centre - mRoundWidth / 2); // 圆环的半径
mPaint.setColor(mRoundColor); // 设置圆环的颜色
mPaint.setStyle(Paint.Style.STROKE); // 设置空心
mPaint.setStrokeWidth(mRoundWidth); // 设置圆环的宽度
mPaint.setAntiAlias(true); // 消除锯齿
canvas.drawCircle(centre, centre, radius, mPaint); // 画出圆环
/**
* 画圆弧 ,画圆环的进度
*/
mPaint.setStrokeWidth(mRoundWidth); // 设置圆环的宽度
mPaint.setColor(mRoundProgressColor); // 设置进度的颜色
RectF oval = new RectF(centre - radius, centre - radius, centre
+ radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
// ,用这个圆的外包矩形的左上角和右下角坐标来确定
// 设置进度是实心还是空心
switch (style) {
case STROKE: {
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(oval, -90, 360 * progress / mMax, false, mPaint); // 根据进度画圆弧
break;
}
case FILL: {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
if (progress != 0)
canvas.drawArc(oval, -90, 360 * progress / mMax, true, mPaint); // 根据进度画圆弧
break;
}
}
/**
* 画进度百分比
*/
mPaint.setStrokeWidth(0);
mPaint.setColor(mProgressTextColor);
mPaint.setTextSize(mProgressTextSize);
mPaint.setTypeface(Typeface.DEFAULT_BOLD); //设置字体
int percent = (int)(((float)progress / (float)mMax) * 100+0.5); //中间的进度百分比,先转换成float在进行除法运算,不然都为0
float textWidth = mPaint.measureText(percent + "%"); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间
if(mTextIsDisplayable && style == STROKE){
canvas.drawText(percent + "%", centre - textWidth / 2, centre + mProgressTextSize/2, mPaint); //画出进度百分比
}
}
此时的效果是:
引用:
Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条) - Mobile Internet developer - 博客频道 - youkuaiyun.com