上一篇讲解了如何创建项目和库,本篇来讲解如何给自定义控件定义属性。
属性定义
首先我们在widgetlib的下创建一个类叫Switch(开关),继承于View,让它继承View的全部构造函数。
接着在values文件夹下创建一个属性声明文件,名字叫attr_switch,一般命名的规则是attr_xxx,表示某控件的属性声明。
文件创建好了,接下我们想想这个控件需要定义什么属性,结合下面的图片来看看。
1.开关打开的颜色(蓝色部分)
2.开关关闭的颜色(灰色部分)
3.开关的底色(红色)
4.开关凹槽的颜色(绿色)
在想想看还需要什么属性呢?能设置的属性越多,这个控件diy的空间就越大。想想看Android Studio自带的TextView,光是一个文本框就有十几种可设置的属性。
5.控制开关大小的内间距(paddingSwitch)
6.控制凹槽的内间距(paddingInside)
7.开关底部的半径(radius)
目前想到的属性就这么多,接下来我们在attr_switch.xml属性文件上声明它们。
<resources>
<declare-styleable name="Switch">
<attr name="OnColor" format="color"/>
<attr name="OffColor" format="color"/>
<attr name="InsideColor" format="color"/>
<attr name="BackColor" format="color"/>
<attr name="SwitchPadding" format="dimension"/>
<attr name="InsidePadding" format="dimension"/>
<attr name="radius" format="dimension"/>
</declare-styleable>
</resources>
declare-styleable 标签是用来绑定控件对应的java文件的。
attr 标签就是用来声明自定义控件属性的,其中name是属性名,format是属性的类型。color是颜色类型,dimension是尺寸类型。
这么一来,属性声明就完成了。我们来试试看是不是定义成功了。
打开app上的MainActivity布局文件。
如果会提示刚刚创建Switch控件,说明目前是成功的了。
在布局文件上放一个我们定义的Switch。注意,由于这些属性是我们自己定义的,而不是Android自带的,所以要在最外层布局加上
xmlns:app=“http://schemas.android.com/apk/res-auto”
自定义属性用app:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.pyjtlk.widgetlib.Switch
android:layout_width="100dp"
android:layout_height="20dp"
app:BackColor="#AA00"
app:InsideColor="#A0A0"
app:OffColor="#AAAAAA"
app:OnColor="#A00A"
app:InsidePadding="5dp"
app:SwitchPadding="3dp"
app:radius="20dp"/>
</LinearLayout>
获取自定义属性
给Switch设置了这么多自定义属性,下面就要获取它们的值,回到Switch.java。
先定义这些私有变量来接收刚刚布局文件上的参数。
public class Switch extends View {
private int mInsideColor;
private int mOnColor;
private int mOffColor;
private int mBackColor;
private int mSwitchPadding;
private int mInsidePadding;
private int mRadius;
...
接着写一个初始化方法。
private void getAttrFromXml(Context context,AttributeSet attrs){
//1
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.Switch);
//2
mInsideColor = typedArray.getColor(R.styleable.Switch_InsideColor, Color.GREEN);
mOnColor = typedArray.getColor(R.styleable.Switch_OnColor, Color.BLUE);
mOffColor = typedArray.getColor(R.styleable.Switch_OffColor, Color.GRAY);
mBackColor = typedArray.getColor(R.styleable.Switch_BackColor, Color.RED);
//3
mSwitchPadding = typedArray.getDimensionPixelSize(R.styleable.Switch_SwitchPadding,0);
mInsidePadding = typedArray.getDimensionPixelSize(R.styleable.Switch_InsidePadding,0);
mRadius = typedArray.getDimensionPixelSize(R.styleable.Switch_radius,0);
//4
typedArray.recycle();
}
先看到代码1和代码4。代码1、代码4分别是打开xml文件和关闭xml文件,在它们之间就是获取参数的操作。
注释2下面的四行代码获取控件定义的颜色属性,颜色值在xml文件的格式是#AABBCCDD,到了java文件上就被转换为整型了。
注释3下面的三行代码获取控件定义的尺寸属性,尺寸属性在xml文件的单位可以是dp、sp、px等,通过getDimensionPixelSize方法可以将其转换为对应的像素个数。
举个例子,如果dp和像素的比例是3:1,那么在xml文件上设置10dp,通过getDimensionPixelSize就的到30,也就是30个像素。
获取到参数了,把它放在构造函数上就行了。
public Switch(Context context) {
super(context);
}
public Switch(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
getAttrFromXml(context,attrs);
}
public Switch(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
getAttrFromXml(context,attrs);
}
public Switch(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
getAttrFromXml(context,attrs);
}
为什么不放在第一个构造函数里呢?因为在java文件里动态生成控件才会用到第一个构造方法。
至此,自定义属性的定义和获取就完成了,但对于整个控件的初始化来说这只是其中很小的一部分,还有很多的工作要做。
最后
下一篇将讲解如何测量控件宽高与绘制。