首页 > 代码库 > Android开发之自定义UI组件和属性

Android开发之自定义UI组件和属性


Android系统虽然自带了很多的组件,但肯定满足我们个性化的需求,所以我们为了开发方便,需要自定义Android的UI组件,以实现我们个性化的需求。

自定义组合控件的步骤:

1 、自定一个View,需要继承相对布局,线性布局等ViewGroup的子类。ViewGroup是一个其他控件的容器,能够乘放各种组件。

2 、实现父类的3个构造方法。一般需要在构造方法里始化初自定义布局文件。

      一个参数构造方法:为new控件使用

     两个参数的造方法:在调用布局文件使用

    两个参数的造方法:传递带有样式的布局文件使用

3 、根据需求,定义一些API方法。

4 、根据需要自定义控件的属性。可以参考TextView的属性写。

5 、自定义命名空间。xmlns:xxx="http://schemas.android.com/apk/res/<包名>"     xxx为为scheam名

6 、自定义我们的属性, 在res/values/attrs.xml(创建属性文件)定义属性

      类似:

    <?xml version="1.0" encoding="utf-8"?>
<resources>


    <declare-styleable name="TextView">


        <!-- 自定义控件的属性 -->
        <attr name="desc_on" format="string" />
        <attr name="desc_off" format="string" />
        <attr name="titles" format="string" />
    </declare-styleable>


</resources>


7 、使用自定义的属性。

    例如:

       andy:desc_off="设置自动更新已经关闭"
        andy:desc_on="设置自动更新已经开启"
        andy:titles="设置自动更新" 


8 、在我们自定义控件的带两个参数的构造方法里面,AttributeSet attrs取出自定属性值,关联到自定义布局文件对应的控件。


代码实例如下;

1 定义一个自定义控件:setting_item_view.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="68dip" >

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dip"
        android:layout_marginTop="8dip"
        android:text="设置是否自动更新"
        android:textColor="#000000"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_desc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        android:layout_marginLeft="10dip"
        android:text="自动更新已经关闭"
        android:textColor="#88000000"
        android:textSize="18sp" />

    <CheckBox
        android:id="@+id/cb_status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dip" />

    <View
        android:clickable="false"
        android:layout_width="match_parent"
        android:layout_height="0.2dip"
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="5dip"
        android:layout_marginRight="5dip"
        android:background="#000000" />

</RelativeLayout>


2 在对应的Activity布局文件中调用  

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:andy="http://schemas.android.com/apk/res/com.andy.mobilesafe"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

   <com.andy.mobilesafe.ui.SettingItemView
        android:id="@+id/siv_update"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        
        andy:desc_off="设置自动更新已经关闭"
        andy:desc_on="设置自动更新已经开启"
        andy:titles="设置自动更新" />
</LinearLayout>

3 自定义属性:res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="TextView">

        <!-- 自定义控件的属性 -->
        <attr name="desc_on" format="string" />
        <attr name="desc_off" format="string" />
        <attr name="titles" format="string" />
    </declare-styleable>

</resources>

4 实现自定义组件,继承ViewGroup的子类,实现构造方法,和对应的API方法

package com.andy.mobilesafe.ui;

import com.andy.mobilesafe.R;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CheckBox;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * @author Zhang,Tianyou
 * @version 2014年11月15日 下午10:22:50
 * 
 *          自定义组合控件 两个TextView 一个checkbox 一个View
 */

public class SettingItemView extends RelativeLayout {

	private CheckBox cb_status;
	private TextView tv_title;
	private TextView tv_desc;

	private String desc_on;
	private String desc_off;

	/**
	 * 初始化布局文件
	 * 
	 * @param context
	 */
	private void initView(Context context) {
		// 第二个为布局文件 root第三个参数为布局文件父类
		// 把一个布局文件 View 并加载在SettingItemView
		View.inflate(context, R.layout.setting_item_view, this);
		// View 已经加载该SettingItemView
		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.title);
	}

	public SettingItemView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// 这个是可以传递一个样式 调用
		initView(context);
	}

	/**
	 * 带有两个参数的构造方法 ,布局文件使用的时间调用
	 * 
	 * @param context
	 * @param attrs
	 *            得到属性值
	 */
	public SettingItemView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 自定义布局使用调用的构造方法 attrs为配置的属性 布局文件中使用
		initView(context);

		String titles = attrs.getAttributeValue(
				"http://schemas.android.com/apk/res/com.andy.mobilesafe",
				"titles");
		desc_off = attrs.getAttributeValue(
				"http://schemas.android.com/apk/res/com.andy.mobilesafe",
				"desc_off");
		desc_on = attrs.getAttributeValue(
				"http://schemas.android.com/apk/res/com.andy.mobilesafe",
				"desc_on");
		tv_title.setText(titles);
		setDesc(desc_off);
	}

	public SettingItemView(Context context) {
		super(context);
		// new 出的时间使用
		initView(context);
	}

	/**
	 * 校验组合控件是否有选中
	 * 
	 * @return
	 */
	public boolean isChecked() {
		return cb_status.isChecked();
	}

	/**
	 * 设置组合控件选中
	 * 
	 * @param checked
	 */
	public void setChecked(boolean checked) {
		if(checked){
			setDesc(desc_on);
		}else {
			setDesc(desc_off);
		}
		
		cb_status.setChecked(checked);
	}

	/**
	 * 设置组合控件的描述信息
	 * 
	 * @param text
	 */
	public void setDesc(String text) {
		tv_desc.setText(text);
	}
}




Android开发之自定义UI组件和属性