在Android开发中经常会用到自定义View的情况,而在自定义View时,自定义属性是必须用到的。
1、新建一个自定义View如CustomView
它的自定义属性主要是通过declare-styleable标签为其配置自定义属性。具体做法是:在res/values/目录下增加一个resources xml文件,示例如下(res/values/attrs.xml)(属性值如字体、颜色、大小等需要传递到代码中获取并使用)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomView">
<attr name="textString" format="string"/>
<attr name="colorValue" format="color"/>
<attr name="textSize" format="dimension"/>
</declare-styleable>
</resources>
在attrs.xml文件中,外层引入了如下标签:
<declare-styleable name="CustomView">
解释:
所有resources文件中声明的属性都会在R.attr类中生成对应的成员变量:
public final class R{
public static final class attr{
public static final int textString=0x7f010038;
public static final int colorValue=0x7f010039;
public static final int textSize=0x7f010040;
}
}
但是声明在标签中的属性,系统还会在R.styleable类中生成相关的成员变量
public static final class styleable{
public static final int[] CustomView={
0x7f010038,0x7f010039,0x7f010040
};
public static final int CustomView_textString=0;
public static final int CustomView_colorValue=1;
public static final int CustomView_textSize=2;
}
可以看出R.styleable.CustomView是一个数组,其中的元素值恰好就是R.attr.textString~textSize的值。而下面的CustomView_textString~CustomView_textSize正好就是其对应的索引。
2、编写布局文件,引用自定义的View
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/BgColor"
<com.example.CustomView
android:id="@+id/customView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:colorValue="@color/textRed"
app:textString="This is the Custom View!!"
app:textSize="21sp"
/>
</LinearLayout>
注意:
新增布局文件的命名空间
因为我们自定义了View,并且自定义了属性,而这些属性不再属于
http://schema.adnroid.com/apk/res/android
这个命名空间属于:
http://schema.android.com/apk/res/[你的项目包名]
所以需要在增加的布局文件中的命名空间改成:
http://schema.adnroid.com/apk/res/com.example
关于自定义View的代码,会在下一篇文章中介绍,这里主要是介绍自定义属性的细节。
format的定义及应用示例:
1、reference:资源引用
属性定义:
<attr name="background" format="reference"/>
使用示例:
<com.example.CustomView
android:layout_width="24dp"
android:layout_height="24dp"
app:background="@mipmap/bg"
/>
2、color:颜色值
属性定义:
<attr name="textColor" format="color"/>
使用示例:
<com.example.CustomView
android:layout_width="24dp"
android:layout_height="24dp"
app:textColor="#000000"
/>
3、boolean:布尔值
属性定义:
<attr name="focusable" format="boolean"/>
使用示例:
<com.example.CustomView
android:layout_width="24dp"
android:layout_height="24dp"
app:foucusable="true"
/>
4、dimension:尺寸值
属性定义:
<attr name="custonWidth" format="demension"/>
属性使用:
<com.example.CustomView
app:customWidth="24dp"
android:layout_height="wrap_content"
/>
5、float:浮点值
属性定义:
<attr name="fromAlpha" format="float"/>
属性使用:
<com.example.CustomView
android:layout_width
android:layout_height
app:fromAlpha="0.5"
/>
6、integer:整型值
属性定义:
<attr name="frameDuration" format="integer"/>
属性使用:
<com.example.CustomView
app:frameDuration="12"
/>
7、string:字符串
属性定义:
<attr name="textString" format="string"/>
属性使用:
<com.example.CustomView
app:textString="hello world!!"
/>
8、fraction:百分数
属性定义:
<attr name="pivotX" format="fraction"/>
属性使用:
<com.example.CustomView
app:pivotX="30%"
/>
9、枚举值
属性定义:
<attr name="orientation">
<enum name="horizontal" value="0"/>
<enum name="vertical" value="1"/>
</attr>
属性使用:
<com.example.CustomView
app:orientation="vertical"
/>
10、flag:位或运算符
属性定义:
<declare-styleable name="CustomView">
<attr name="windowSoftInputMode">
<flag name = "stateUnspecified" value = "0" />
<flag name = "stateUnchanged" value = "1" />
<flag name = "stateHidden" value = "2" />
<flag name = "stateAlwaysHidden" value = "3" />
<flag name = "stateVisible" value = "4" />
<flag name = "stateAlwaysVisible" value = "5" />
<flag name = "adjustUnspecified" value = "0x00" />
<flag name = "adjustResize" value = "0x10" />
<flag name = "adjustPan" value = "0x20" />
<flag name = "adjustNothing" value = "0x30" />
</attr>
</declare-styleable>
属性使用:
<com.example.CustomView
app:windowSoftInputMode="stateUnspecified|stateUnchanged|stateHidden"
/>
补充:
(2018-12-12)
在代码构造器中引用时需要注意TypedArray、AttributeSet这两个点,例如:
public CustomView(Context context){
this(context,null);
}
public CustomView(Context context,AttributeSet attrs){
this(context,attrs,0);
}
public CustomView(Context context,AttributeSet attrs,int defStyleAttr){
super(context,attrs,defStyleAttr);
TypedArray array=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomView,defStyleAttr);
int count=array.getIndexCount();
for(int i=0;i<count;i++){
switch(i){
case R.styleable.CustomView_attrs_text://声明:在styleable中它的名字为attrs_text
text=array.getString(index);
break;
case R.styleable.CustomView_attrs_text_color:
texcolor=array.getInt(index,Color.BLACK);
break;
case R.styleable.CustomView_attrs_text_size:
textsize=array.getDimensionPixelSize(index16);
break;
......
}
关于TypedArray和AttributeSet
AttributeSet的作用就是在控件进行初始化的时候,解析布局文件中该控件的属性(keyeg:background)与该值(valueeg:@drawable/icon)的信息封装在AttributeSet中,传递给该控件的构造函数。
对于非Android自带的属性,在View类中处理时是无法识别的,需要我们自己解析。所以需要用到TypedArray。在AttributeSet中有属性名称和属性值,TypedArray的工作就是来告诉控件哪个属性代表什么意思。
TypedArray对象封装了/values/attrs.xml中的styleable里定义的每个属性的类型信息,通过TypedArray就可以知道AttributeSet中封装的值的类型,从而可以对这些数据进行应用。