安卓自定义属性主要有3个步骤
在values文件夹新建attrs.xml文件中声明属性,包括属性名和格式,format常用属性有string ,integer,reference等
<?xml version="1.0" encoding="utf-8"?>
<resources > <declare-styleable name ="MyToggleButtton" > <attr name ="my_background" format ="reference" /> <attr name ="my_slide_btn" format ="reference" /> <attr name ="curr_state" format ="boolean" /> </declare-styleable > </resources >
在布局文件中使用,使用之前必须先声明命名空间,前面是固定不变的内容,后面是包名.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:zj="http://schemas.android.com/apk/res/com.zj.switchbutton" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage} .${activityClass} " ><com.zj.switchbutton.MyTrouggleButtonandroid:layout_width="wrap_content" android:layout_height="wrap_content" zj:my_background="@drawable /switch_background" zj:my_slide_btn="@drawable /slide_button" zj:curr_state="true" /></RelativeLayout>
在自定义view的构造方法中,通过解析AttributeSet方法,获得所需要的属性值,解析AttributeSet主要有两种方法
第一种:通过attrs.getAttributeValue获得
int counts=attrs.getAttributeCount();for (int i=0 ;i<counts;i++){attrs.getAttributeName(i);attrs.getAttributeValue(i);}public SettingItemView (Context context, AttributeSet attrs) {super (context, attrs);iniView(context);String title = attrs.getAttributeValue("http://schemas.android.com/apk/res/com.zj.mobilesafe" , "mytitle" );desc_on = attrs.getAttributeValue("http://schemas.android.com/apk/res/com.zj.mobilesafe" , "desc_on" );desc_off = attrs.getAttributeValue("http://schemas.android.com/apk/res/com.zj.mobilesafe" , "desc_off" );tv_title.setText(title);setDesc(desc_off);}
第二种:通过TypedArray获得
public MyTrouggleButton (Context context, AttributeSet attrs) {super (context, attrs);TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyToggleButtton);int N=ta.getIndexCount();for (int i=0 ;i<N;i++){int itemId=ta.getIndex(i);switch (itemId) {case R.styleable.MyToggleButtton_curr_state:current_state=ta.getBoolean(itemId, false );break ;case R.styleable.MyToggleButtton_my_background:backgroundID=ta.getResourceId(itemId, -1 );if (backgroundID==-1 ){throw new RuntimeException("请设置背景图片" );}backgroundBitmap=BitmapFactory.decodeResource(getResources(),backgroundID);break ;case R.styleable.MyToggleButtton_my_slide_btn:slideButtonID=ta.getResourceId(itemId, -1 );if (backgroundID==-1 ){throw new RuntimeException("请设置图片" );}slideBtnBitmap=BitmapFactory.decodeResource(getResources(), slideButtonID);default :break ;}}init();}
自定义属性到底有什么用呢?当界面上的自定义元素有一些值需要改变并且大量重复的时候,自定义属性可以有效的提高代码的重用性,下面是一个简单的例子
声明属性
<?xml version="1.0" encoding="utf-8"?>
<resources > <declare-styleable name ="TextView" > <attr name ="mytitle" format ="string" /> <attr name ="desc_on" format ="string" /> <attr name ="desc_off" format ="string" /> </declare-styleable >
</resources >
在xml文件中定义
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:zj="http://schemas.android.com/apk/res/com.zj.mobilesafe" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" ><TextViewandroid:id="@+id/textView1" android:layout_width="fill_parent" android:layout_height="55dip" android:background="#8866ff00" android:gravity="center" android:text="设置中心" android:textColor="#000000" android:textSize="22sp" /><com .zj .mobilesafe .ui .SettingItemView android:id="@+id/siv_update" android:layout_width="wrap_content" android:layout_height="65dip" zj:desc_off="设置自动更新已经关闭" zj:desc_on="设置自动更新已经开启" zj:mytitle="设置自动更新" ></com .zj .mobilesafe .ui .SettingItemView ><com .zj .mobilesafe .ui .SettingItemView android:id="@+id/siv_show_address" android:layout_width="wrap_content" android:layout_height="65dip" zj:desc_off="设置显示号码归属地已经关闭" zj:desc_on="设置显示号码归属地已经开启" zj:mytitle="设置显示号码归属地" ></com .zj .mobilesafe .ui .SettingItemView ><com .zj .mobilesafe .ui .SettingClickView android:id="@+id/scv_changebg" android:layout_width="wrap_content" android:layout_height="65dip" ></com .zj .mobilesafe .ui .SettingClickView ><com .zj .mobilesafe .ui .SettingItemView android:id="@+id/siv_callsms_safe" android:layout_width="wrap_content" android:layout_height="wrap_content" zj:desc_off="黑名单拦截已经关闭" zj:desc_on="黑名单拦截已经开启" zj:mytitle="黑名单拦截设置" ></com .zj .mobilesafe .ui .SettingItemView ><com .zj .mobilesafe .ui .SettingItemView android:id="@+id/siv_watchdog" android:layout_width="wrap_content" android:layout_height="wrap_content" zj:desc_off="看门狗已经关闭" zj:desc_on="看门狗已经开启" zj:mytitle="程序锁设置" ></com .zj .mobilesafe .ui .SettingItemView ></LinearLayout>
解析属性并且改变属性
/*** 自定义的组合控件* @author Administrator**/
public class SettingItemView extends RelativeLayout {private CheckBox cb_status;private TextView tv_desc;private TextView tv_title;private String desc_on;private String desc_off;/*** 初始化布局文件* @param context*/ private void iniView (Context context) {View.inflate(context, R.layout.setting_item_view, SettingItemView.this );cb_status=(CheckBox) this .findViewById(R.id.cb_status);tv_desc=(TextView) this .findViewById(R.id.tv_desc);tv_title=(TextView) this .findViewById(R.id.tv_title);}public SettingItemView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle);iniView(context);}/*** 带有两个参数的构造方法,布局文件使用的时候调用 * @param context* @param attrs*/ public SettingItemView (Context context, AttributeSet attrs) {super (context, attrs);iniView(context);String title = attrs.getAttributeValue("http://schemas.android.com/apk/res/com.zj.mobilesafe" , "mytitle" );desc_on = attrs.getAttributeValue("http://schemas.android.com/apk/res/com.zj.mobilesafe" , "desc_on" );desc_off = attrs.getAttributeValue("http://schemas.android.com/apk/res/com.zj.mobilesafe" , "desc_off" );tv_title.setText(title);setDesc(desc_off);}public SettingItemView (Context context) {super (context);iniView(context);}/*** * 检验组合和控件是否有焦点*/ public boolean isChecked (){return cb_status.isChecked();}/*** 设置组合控件的是否选中*/ public void setChecked (boolean checked){if (checked){setDesc(desc_on);}else {setDesc(desc_off);}cb_status.setChecked(checked);}/*** 组合控件 的内容发生改变* */ public void setDesc (String text){tv_desc.setText(text);}}
效果如下