当我们需要实现一些特定的布局显示的时候,我们需要自定义一个控件。自定义控件一般都是继承某种View,然后在里面实现onMesure方法和onLayout方法。
当我们使用自定义控件的时候,我们很希望这个控件能像安卓内部的其它控件一样可以通过在布局文件中写好属性,就能控制着个控件,例如
android:layout_width="match_parent"
这样这个控件的宽度就会和它的父View一样大小。
今天我们要说的就是如何让自定义的控件也能像安卓自带的控件一样,通过在XML文件中写好属性的值就能控制这个控件的特性。
1.先定义好属性文件在:/res/values/attr.xml中添加attr.xml文件,内容如下
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<attr name="rightPadding" format="dimension"></attr>
<declare-styleable name="SlidingMenu">
<attr name="rightPadding"></attr>
</declare-styleable>
</resources>
这个文件里定义了一个styleable,这个styleable里有一个属性rightPadding,当然你可以在一个styleable里有很多属性
2.在使用自定义布局的文件里面使用自定义属性
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:hyman="http://schemas.android.com/apk/res/com.cyq.slight_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<com.cyq.view.SlideMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
hyman:rightPadding="100dp"
>
这边需要添加两个地方,一个是命名空间xmlns:hyman=”http://schemas.android.com/apk/res/com.cyq.slight_menu”
这个命名空间前半部分和上面的一样,后半部分是程序的包名,切记是程序的包名,不是其他包名。
,还有一个就是属性了hyman:rightPadding=”100dp”,这里使用了我们上面定义的命名空间,这个名称是可以随便取的。
3然后,也是最后一部分,我们要在自定义控件的类里面获取自定义的属性,至于如何使用获取后的属性,就要看各位的奇思妙想了。
以下是获取自定义属性的值的代码
/**
* new 的时候调用
* @param context
*/
public SlideMenu(Context context) {
this(context,null);
}
/**
* 未使用自定义属性时 调用
*
* @param context
* @param attrs
*/
public SlideMenu(Context context, AttributeSet attrs) {
this(context,attrs,0);
}
/**
* 当使用了自定义的属性时,会调用此构造方法
* @param context
* @param attrs
* @param defStyle
*/
public SlideMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//获取自定义属性
TypedArray mTypedArray=context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenu, defStyle, 0);
int n=mTypedArray.getIndexCount();//获取属性的个数
for (int i = 0; i < n; i++) {//循环每个属性
int attr=mTypedArray.getIndex(i);
switch (attr) {
case R.styleable.SlidingMenu_rightPadding:
mMenuRight_padding=mTypedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
.getDisplayMetrics()));
}
}
//用完后要释放
mTypedArray.recycle();
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
// 执行下面两个后,DisplayMetrics就能拿到宽和高了
DisplayMetrics outMetrics = new DisplayMetrics();
// 这个方法执行后就拿到高度和宽度的值了
wm.getDefaultDisplay().getMetrics(outMetrics);
// 获得屏幕的宽
mScreenWidth = outMetrics.widthPixels;
// 将50dp转换成一个像素值px
mMenuRight_padding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
.getDisplayMetrics());
}
其他的你先不要看,你就看一共有三种构造方法,至少在这边是三种,其它的可能会有不同,但肯定有一种是在使用到了自定义属性时才会调用的构造方法。然后,在这个构造方法中使用TypedArray ,获得属性的集合通过这个集合来获取自定义的属性(如何通过TypedArray 获取属性值,详情请参考代码)