一直对自定义属性停留在知道概念,但每次用都要上网搜索,并且不太明白自定义属性的原理,基于最近的一个自定义控件进行了一下总结,方便日后不用再在需要使用的时候再去谷歌。而且弄清楚了自定义属性的基本原理。
一. 基本原理:
1. 每一个UI控件在layout的xml布局中定义,然后在Activity的onCreat方法中通过调用setContentView(R.layout.XX)进行加载调用。(好像是运用反射实例化加载的)
2. 或者通过LayoutInflater.from(this).inflate(R.layout.XX, null);把一个布局文件转换成一个View
底层的示例化方法还需要研究(给自己定为下一个课题吧)
二. 自定义属性的步骤
1. 根据需要在values文件夹下的attrs文件中定义一个属性集合 declare-styleable ,此处模拟定义属性 name、age、 head.
<!--定义一个属性集合-->
<declare-styleable name="MyAttrsView">
<!--定义一个叫name的属性-->
<attr name="name" format="string"/>
<attr name="age" format="integer"/>
<attr name="head" format="reference|color"/>
</declare-styleable>
- 自定义一个View或者ViewGroup ,此处为了记录 定义一个MyAttrsView 继承自View
public class MyAttrsView extends View {
public MyAttrsView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
- 在layout的xml中引用这个类
其中添加了如下三个属性,属性前的chris自由定义 name , age ,head需要包含在attrs文件定义的属性name之中
chris:age = “27”
chris:name = “ChrisYu”
chris:head = “@drawable/devices_icon”
然后会提示添加自定义属性的命名空间,命名空间有点类似于引用路劲的意思
xmlns:chris=”http://schemas.android.com/apk/res-auto”
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:chris="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.koti.www.myuidemo.myattrs.MyAttrsView
android:layout_width="match_parent"
android:layout_height="wrap_content"
chris:age = "27"
chris:name = "ChrisYu"
chris:head = "@drawable/devices_icon"
/>
</LinearLayout>
- 然后载回到自定义的MyAttrsView中,获取自定义的属性并进行相应的操作:
一般用的最多的是第三种方法,
//获取属性的三种方式
//1. 利用命名控件获取
String name = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto" ,"name");
String age = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto" ,"age");
String head = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto" ,"head");
Log.e(TAG, "MyAttrsView: name = " + name + " age = " +age + " head = " + head);
//2. 通过遍历属性的方式
for (int i = 0; i < attrs.getAttributeCount() ; i++) {
Log.i(TAG, attrs.getAttributeName(i) + "====" + attrs.getAttributeValue(i));
}
//3. 使用系统工具获取属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyAttrsView);
for (int i = 0; i < typedArray.getIndexCount() ; i++){
int index = typedArray.getIndex(i);
switch (index){
case R.styleable.MyAttrsView_name:
name1 = typedArray.getString(index);
break;
case R.styleable.MyAttrsView_age:
age1 = typedArray.getInt(index,0);
break;
case R.styleable.MyAttrsView_head:
Drawable head1 = typedArray.getDrawable(index);
BitmapDrawable drawableBit = (BitmapDrawable) head1;
headb = drawableBit.getBitmap();
break;
}
}
typedArray.recycle();
//和上面一样,只是没有使用遍历的方式得到属性。
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyAttrsView, defStyle, 0);
name1 = a.getString(R.styleable.MyAttrsView_name);
age1= a.getInt(R.styleable.MyAttrsView_age , 0);
Drawable head1 = a.getDrawable(R.styleable.MyAttrsView_head);
a.recycle();