Android自定义控件之自定义属性(二)主要涉及到在自定义控件中自定义属性的使用方法,其完整攻略如下:
1. 前言
在Android中,自定义View是非常常见的需求,而自定义控件之一的自定义属性,也是比较重要的一部分,通过自定义属性,我们可以方便地在XML文件中设置控件的属性,这样可以大大提高我们的开发效率。在之前的博客中,我们已经学习了如何自定义属性,但是那次只是介绍了自定义属性的基本用法,这次我们会更深入地学习如何在自定义控件中使用自定义属性。
2. 自定义属性的使用
2.1 属性声明
在创建自定义属性之前,需要在res/values/attrs.xml文件中进行属性的声明。如:
<resources>
<declare-styleable name="MyCustomView">
<attr name="textColor" format="color"/>
<attr name="textSize" format="dimension"/>
<attr name="text" format="string"/>
</declare-styleable>
</resources>
上面的代码中,我们定义了一个叫做MyCustomView的样式,其中包含了三个属性:
- textColor:字体颜色,属性类型为color。
- textSize:字体大小,属性类型为dimension。
- text:显示的文本,属性类型为string。
其中,name表示属性的名称,format表示属性的值类型。format主要有以下选择:
-
reference:引用类型,用@符号指定资源ID,如@drawable/my_bg。
-
color:颜色类型,用#符号指定颜色,如#FF0000。
-
dimension:尺寸类型,如10dp, 20sp等。
-
float:浮点数类型,如3.14。
-
boolean:布尔类型,如true或false。
2.2 在布局文件中使用
在Activity的布局文件中使用自定义属性时,只需要加上自定义命名空间,例如:
<com.example.view.MyCustomView
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:textColor="#FF0000"
custom:textSize="20sp"
custom:text="hello, world!"/>
其中的xmlns:custom="http://schemas.android.com/apk/res-auto"是必须的,这样才能使用自定义命名空间。
2.3 在代码中获取属性值
在自定义控件中获取自定义属性的值,需要重写View的构造函数,如:
public class MyCustomView extends View {
private int textColor;
private float textSize;
private String text;
public MyCustomView(Context context) {
this(context, null);
}
public MyCustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
textColor = ta.getColor(R.styleable.MyCustomView_textColor, Color.BLACK);
textSize = ta.getDimension(R.styleable.MyCustomView_textSize, 16);
text = ta.hasValue(R.styleable.MyCustomView_text) ? ta.getString(R.styleable.MyCustomView_text) : "";
ta.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(textColor);
paint.setTextSize(textSize);
canvas.drawText(text, 50, 50, paint);
}
}
在代码中,我们通过调用Context的obtainStyledAttributes方法获取TypedArray来获取属性值,这个方法的参数有两个:
- AttributeSet attrs:继承View的子类一般都会有三个参数的构造方法,其中第二个参数就是AttributeSet类型的。这里的attrs指的就是我们在XML布局文件中添加的属性。
- int[] attrsArray:一个int类型的数组,它保存我们需要获取的属性ID,也就是我们在res/values/attrs.xml中所声明的属性。
在获取属性值时,我们一般使用了三个方法:
- getColor(int index, int defValue):获取颜色值,如果取出来的值为NULL,就用Entry的默认值(默认值一定要传入)
- getDimension(int index, float defValue):获取尺寸值,参数同上
- getString(int index):获取字符串值
2.4 示例
例如,我们自定义一个ProgressBar控件,它包含了两个属性:progressColor和progressHeight。属性的定义和使用如下:
<resources>
<declare-styleable name="ProgressBar">
<attr name="progressColor" format="color"/>
<attr name="progressHeight" format="dimension"/>
</declare-styleable>
</resources>
<com.example.view.ProgressBar
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
custom:progressColor="#FF0000"
custom:progressHeight="10dp"/>
ProgressBar的具体实现如下:
public class ProgressBar extends View {
private int progressColor = Color.RED;
private float progressHeight = 5;
private Paint mPaint;
public ProgressBar(Context context) {
super(context);
init(context, null);
}
public ProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final float percentage = 0.5f;//计算出当前进度占总宽度的百分比
final float progressWidth = getWidth() * percentage;
mPaint.setColor(progressColor);
mPaint.setStrokeWidth(progressHeight);
canvas.drawLine(0, getHeight() / 2, progressWidth, getHeight() / 2, mPaint);
}
/**
* 初始化
*/
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
progressColor = array.getColor(R.styleable.ProgressBar_progressColor, Color.RED);
progressHeight = array.getDimension(R.styleable.ProgressBar_progressHeight, 5);
array.recycle();
}
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
}
两个属性的绑定在构造函数中实现。可以看到,ProgressBar的实现与TextView的类似,只需要重写onDraw方法即可。其中,获取自定义属性值的代码,就在构造方法中使用了TypedArray类实现。
3. 总结
自定义属性作为自定义控件的一部分是非常重要的,可以通过自定义属性方便地在XML文件中设置控件属性,提高我们的开发效率。同时,我们也需要了解如何在代码中获取属性值,这样才能发挥自定义属性的效果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android自定义控件之自定义属性(二) - Python技术站