需求:在黑马做安全卫士的时候,功能9设置中心界面如下:
在点击item的时候,复选框会反转状态,同时"自动更新已经关闭"会变换内容和颜色。
可以发现这个界面类似ListView,但又不是ListView,因为它的item数量是固定的,且最后一
item和之前的都不一样。虽然这个看着像是标准的List结构,实则每个item不是完全一样,因为
每个item的提示文本(如"自动更新已经关闭")的内容并不完全一样。
假如用一般方式来布局的话,4个item就会有3*4 = 12个view,就会有多个findViewById()和
onClick事件。那么程序就会显得十分的臃肿和冗余。
假如用ListView来布局的话,4个item就会有4个view,给item项添加item点击事件即可。但是
上面已经说到,4个item并不是完全标准的ListView的item,每个item项的提示文本内容是独立
的。如果一定要用ListView来实现的话,那么只要多声明两个数组来存放复选框两种状态各个
item的提示信息。虽然ListView也能实现想要的功能,但是有点大材小用的感觉,而且复用性差.
为了解决上面这一问题,于是自定义组合控件的技术出现了。
1. 什么是自定义组合控件
自定义组合控件,还不如说是自定义组合控件类。就是将多个控件封装到一个容器里,将整个容
器看作一个控件。所有的控件还是用代码,用相应的类来实现的。
■自定义组合控件的特点
1) 冗余度低
2)复用性强
2. 自定义组合控件的实现
将每个item看作一个自定义组合控件,它应该有title、desc_on、desc_off、check四个属性。
将不同状态的提示文本属性信息封装在控件里,这样比较适于管理和控制。
1)设计自定义控件的布局
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<?
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
=
"match_parent"
android:background
=
"#F0F0F0"
>
<!-- 标题 -->
<
TextView
android:id
=
"@+id/tv_title"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:layout_alignParentTop
=
"true"
android:layout_marginLeft
=
"5dp"
android:layout_marginTop
=
"5dp"
android:text
=
"标题"
android:textSize
=
"20dp"
android:textStyle
=
"bold"
/>
<!-- 描述 -->
<
TextView
android:id
=
"@+id/tv_desc"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:layout_alignLeft
=
"@id/tv_title"
android:layout_below
=
"@id/tv_title"
android:layout_marginTop
=
"5dp"
android:text
=
"描述"
android:textSize
=
"15dp"
/>
<!-- 复选框 -->
<!-- 将下面的两个属性设置为false,可以屏蔽复选框的点击事件。因为我想通过点击整个自定义控件从而控制复选框的变化。 -->
<!-- android:clickable="false" -->
<!-- android:focusable="false" -->
<
CheckBox
android:id
=
"@+id/cb_check"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_alignParentRight
=
"true"
android:layout_marginRight
=
"5dp"
android:clickable
=
"false"
android:focusable
=
"false"
/>
</
RelativeLayout
>
|
布局效果:
2)创建自定义控件类继承布局
3)创建项目的自定义命名空间文件
■系统的命名空间
其实这个属性指向的是一个系统自带的attr.xml文件,在系统的values文件夹目录下,它指定了什么控件
会有什么属性。
系统自带的这个attr.xml文件里,定义了系统自带的所有控件的属性。
》系统attr.xml文件的根结点标签
》比如ImageView控件
控件是用<declare-styleable>标签来声明的,用<attr>标签指定控件的属性。
■自定义的命名空间
》参照系统的自定义命名空间文件的格式,在自己的项目里values文件夹下新建一个
同样名称的attr.xml文件
可以在values目录下新建attr.xml文件的时候,会自动提示根标签resources,与
系统自带的attr.xml文件格式一样。
》》在新建的values/attr.xml文件里声明自定义控件及其属性
[转]【android】多个类定义attr属性重复的问题:Attribute "xxx" has already been defined
http://m.blog.csdn.net/blog/u011494050/44829267
Attribute "title" has already been defined - 姜家志
http://www.880688.com/program/osprojects/programdev/325300.htm
全局搜索包含title的.xml文件,发现V7包中support/v7/appcompat/res/values/attrs.xml中也有title属性。
》》》在activity布局里加上自定义命名空间,引用自定义布局控件。
如果是使用依赖库的自定义属性,包名写本App的包名,而不是依赖库的包名
》》》》自定义控件的初始化
上面这种方式获取自定义属性需要对reference和xxx进行判断,否则会发生异常。
另外一种获取自定义属性的方式:
1
2
3
4
|
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.RelativeHorizontalItemView);
//得到自定义属性
String leftText = (String) typedArray.getText(R.styleable.RelativeHorizontalItemView_leftText);
|
自定义控件内部定义的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// 自定义两个事件得到复选框的选中状态和设置它的状态
// 显示
public
boolean
isCheck() {
return
cb_check.isChecked();
}
// 设置
public
void
setCheck(
boolean
isChecked) {
cb_check.setChecked(isChecked);
updateCheck();
}
// 更新复选框的状态及配置文件中标记
public
void
updateCheck() {
if
(isCheck()) {
tv_desc.setText(descOnValue);
tv_desc.setTextColor(Color.GREEN);
}
else
{
tv_desc.setText(descOffValue);
tv_desc.setTextColor(Color.RED);
}
//将状态写入标记
SPUtils.config_SetBooleanValue(getContext(),
"autoUpdate"
, isCheck());
}
|
在activity里添加自定义控件点击事件,完善逻辑:
1
2
3
4
5
6
7
8
9
|
//item1监听事件
update_item.setOnClickListener(
new
MySettingCenterItemView.OnClickListener() {
@Override
public
void
onClick(View v) {
/*定义自定义控件MySettingCenterItemView的时候,写了两个方法,就是因为不能直接访问它的组合子控件。
通过方法就能获取和设置它的组合子控件的属性值了。 */
update_item.setCheck(!update_item.isCheck());
}
});
|
拓展:
Android中自定义属性(attrs.xml,TypedArray)的使用
http://www.oschina.net/code/snippet_163910_6283
本文转自屠夫章哥 51CTO博客,原文链接:http://blog.51cto.com/4259297/1683192,如需转载请自行联系原作者