转:http://blog.youkuaiyun.com/xiaanming/article/details/10298163
http://blog.youkuaiyun.com/lmj623565791/article/details/24252901/
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
[ 3、重写onMesure ]
4、重写onDraw
我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的。
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RoundProgressBar">
<attr name="roundColor" format="color" />
<attr name="roundProgressColor" format="color" />
<attr name="roundWidth" format="dimension" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
我们定义了字体,字体颜色,字体大小3个属性,format是值该属性的取值类型:
一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;。
然后在布局中声明我们的自定义View
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app_custom="http://schemas.android.com/apk/res-auto"
tools:context="example.com.roundprogress.MainActivity">
<example.com.roundprogress.ui.RoundProgressBar
android:layout_centerInParent="true"
android:id="@+id/p_progress"
android:layout_width="120dp"
android:layout_height="120dp"
app_custom:roundColor="@android:color/darker_gray"
app_custom:roundProgressColor="@android:color/holo_red_dark"
app_custom:roundWidth="5dp"
app_custom:textColor="#18b4ed"
app_custom:textSize="20sp"
>
</example.com.roundprogress.ui.RoundProgressBar>
</RelativeLayout>
Eclipse中对于自定义属性的引用是在根布局文件中声明一个命名空间引入 xmlns:app_custom="http://schemas.android.com/apk/res/xxxxx"我们的命名空间,后面的xxxxxx包路径指的是项目的package
而在Android Studio中声明命名控件和在Eclipse中类似,例如:xmlns:app_custom=”http://schemas.android.com/apk/res-auto”,
2、在View的构造方法中,获得我们的自定义的样式
public class RoundProgressBar extends View {
private Paint paint = new Paint();
private int roundColor;
private int roundProgressColor;
private int textColor;
private float textSize;
private float roundWidth;
private int max = 100;
private int progress = 50;
public RoundProgressBar(Context context) {
this(context, null);
}
public RoundProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取自定义属性值
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);
//圆环颜色
roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED);
//圆环进度条颜色
roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN);
//中间文字进度的字体的颜色
textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.GREEN);
//中间文字进度的字体的大小
textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 15);
//圆环的宽度
roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 5);
mTypedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
//第一步:绘制一个最外层的圆
paint.setColor(roundColor); //设置圆环的颜色
paint.setStrokeWidth(roundWidth);//设置圆环的宽度
paint.setStyle(Paint.Style.STROKE);//设置空心
paint.setAntiAlias(true);//消除锯齿
int center = getWidth() / 2;//获取圆心的x坐标
int radius = (int) (center - roundWidth / 2);//圆环的半径
canvas.drawCircle(center, center, radius, paint);//画出圆环
//第二步:绘制正中间的文本
float textWidth = paint.measureText(progress + "%");
paint.setColor(textColor);
paint.setTextSize(textSize);
paint.setStrokeWidth(0);
paint.setTypeface(Typeface.MONOSPACE); //设置字体
canvas.drawText(progress + "%", center - textWidth / 2, center + textSize / 2, paint);
//第三步
//第三步:
/**
* 参数解释:
* oval:绘制弧形圈所包含的矩形范围轮廓
* 0:开始的角度
* 360 * progress / max:扫描过的角度
* false:是否包含圆心
* paint:绘制弧形时候的画笔
*/
RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
paint.setColor(roundProgressColor);
paint.setStrokeWidth(roundWidth);
paint.setStyle(Paint.Style.STROKE);
canvas.drawArc(oval, 0, 360 * progress / max, false, paint);
}
public void setProgress(int progress) {
this.progress = progress;
if (progress > 100) {
this.progress = 100;
}
postInvalidate();
}
}
我们重写了3个构造方法,默认的布局文件调用的是两个参数的构造方法,所以记得让所有的构造调用我们的三个参数的构造,我们在三个参数的构造中获得自定义属性。
3、我们重写onDraw,onMesure调用系统提供的:
@Override
protected void onDraw(Canvas canvas) {
//第一步:绘制一个最外层的圆
paint.setColor(roundColor); //设置圆环的颜色
paint.setStrokeWidth(roundWidth);//设置圆环的宽度
paint.setStyle(Paint.Style.STROKE);//设置空心
paint.setAntiAlias(true);//消除锯齿
int center = getWidth() / 2;//获取圆心的x坐标
int radius = (int) (center - roundWidth / 2);//圆环的半径
canvas.drawCircle(center, center, radius, paint);//画出圆环
//第二步:绘制正中间的文本
float textWidth = paint.measureText(progress + "%");
paint.setColor(textColor);
paint.setTextSize(textSize);
paint.setStrokeWidth(0);
paint.setTypeface(Typeface.MONOSPACE); //设置字体
canvas.drawText(progress + "%", center - textWidth / 2, center + textSize / 2, paint);
//第三步
//第三步:
/**
* 参数解释:
* oval:绘制弧形圈所包含的矩形范围轮廓
* 0:开始的角度
* 360 * progress / max:扫描过的角度
* false:是否包含圆心
* paint:绘制弧形时候的画笔
*/
RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
paint.setColor(roundProgressColor);
paint.setStrokeWidth(roundWidth);
paint.setStyle(Paint.Style.STROKE);
canvas.drawArc(oval, 0, 360 * progress / max, false, paint);
}