ListView在Android开发中是比较常用的系统组件,但是有时候我们除了需要做ListView上每一行的点击监听事件之外,如果每一行上还有其他需要监听的控件例如Button、CheckBox等,就必须要进行特殊的处理。
本文自定义的ListView,实现了ListView的每一项和上面的Button按钮能同时监听点击事件(其他控件的做法与Button一样),并且使用通用适配器ListSimpleAdapter,相对于普通的ListActivity,更具扩展性,适配器上可以很容易添加更多各式的控件。
最终效果:
先写listsimpleadapter.xml,这个是ListView每一项的布局文件。如果想在每一项上要添加其他的控件,可以修改此文件。
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
45
46
47
48
49
50
51
52
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
orientation
=
"horizontal"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
gravity
=
"center_vertical"
android
:
padding
=
"10dip"
>
<
ImageView
android
:
id
=
"@+id/pic"
android
:
layout_width
=
"50dp"
android
:
layout_height
=
"50dp"
android
:
padding
=
"10dp"
android
:
layout_gravity
=
"top"
android
:
background
=
"@drawable/ava"
/
>
<
RelativeLayout
xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
android
:
orientation
=
"vertical"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
gravity
=
"right"
android
:
paddingLeft
=
"10dp"
android
:
paddingTop
=
"6dp"
android
:
paddingBottom
=
"6dp"
>
<
TextView
android
:
id
=
"@+id/title"
android
:
layout_width
=
"180dip"
android
:
layout_height
=
"wrap_content"
android
:
textSize
=
"16dip"
/
>
<
TextView
android
:
id
=
"@+id/content"
android
:
layout_width
=
"180dip"
android
:
layout_height
=
"wrap_content"
android
:
layout_below
=
"@id/title"
android
:
layout_marginTop
=
"5dip"
android
:
textSize
=
"15dip"
/
>
<
/
RelativeLayout
>
<
LinearLayout
android
:
orientation
=
"vertical"
android
:
layout_width
=
"fill_parent"
android
:
layout_height
=
"wrap_content"
android
:
gravity
=
"right"
>
<
!
--
注意此处需把
Button的焦点
focusable设置为不可见,
CheckBox也一样
--
>
<
Button
android
:
id
=
"@+id/button"
android
:
layout_width
=
"wrap_content"
android
:
layout_height
=
"wrap_content"
android
:
focusable
=
"false"
/
>
<
/
LinearLayout
>
<
/
LinearLayout
>
|
自定义通用适配器的java代码。For循环中是对ListView中每一项中包含所有的组件进行判定每个组件的类型,从而去设置其数据。其中【instanceof】这个关键字是对Object 类型的判断。
这里要特别指出,由于textview的某种原因,我也不是很清楚,只是经过测试,如果其他类似于Button、CheckBox等控件设置在textview的后面,其对应的代码将不执行,也就是说程序运行时把button和CheckBox都映射成了textview,故执行了textview中的代码。这个问题现在我也不知道原因所在。但是如果将Button、CheckBox等控件设置放在textview之前,代码正常运行。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package
tabhost
.
demo
.
widget
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
tabhost
.
demo
.
TestActivity
;
import
android
.
app
.
AlertDialog
;
import
android
.
content
.
Context
;
import
android
.
util
.
Log
;
import
android
.
view
.
LayoutInflater
;
import
android
.
view
.
View
;
import
android
.
view
.
ViewGroup
;
import
android
.
widget
.
BaseAdapter
;
import
android
.
widget
.
Button
;
import
android
.
widget
.
ImageView
;
import
android
.
widget
.
TextView
;
public
class
ListSimpleAdapter
extends
BaseAdapter
{
private
LayoutInflater
layoutinflater
;
private
List
<
Map
<
String
,
Object
>>
list
;
private
int
layoutId
;
private
String
flag
[
]
;
private
int
ItemId
[
]
;
public
ListSimpleAdapter
(
Context
context
,
List
<
Map
<
String
,
Object
>>
list
,
int
layoutId
,
String
flag
[
]
,
int
ItemId
[
]
)
{
this
.
layoutinflater
=
LayoutInflater
.
from
(
context
)
;
this
.
list
=
list
;
this
.
layoutId
=
layoutId
;
this
.
flag
=
flag
;
this
.
ItemId
=
ItemId
;
}
//调用并显示view的条数
@Override
public
int
getCount
(
)
{
return
list
.
size
(
)
;
}
@Override
public
Object
getItem
(
int
arg0
)
{
return
0
;
}
@Override
public
long
getItemId
(
int
arg0
)
{
return
0
;
}
@Override
public
View
getView
(
int
position
,
View
convertView
,
ViewGroup
parent
)
{
convertView
=
layoutinflater
.
inflate
(
layoutId
,
null
)
;
//填充数据到对应的控件中,注意此处的textview应写在最后面,才能正常实例化控件
for
(
int
i
=
0
;
i
<
flag
.
length
;
i
++
)
{
if
(
convertView
.
findViewById
(
ItemId
[
i
]
)
instanceof
ImageView
)
{
ImageView
imageView
=
(
ImageView
)
convertView
.
findViewById
(
ItemId
[
i
]
)
;
imageView
.
setBackgroundResource
(
(
Integer
)
list
.
get
(
position
)
.
get
(
flag
[
i
]
)
)
;
Log
.
e
(
"type"
,
"imageview"
)
;
}
else
if
(
convertView
.
findViewById
(
ItemId
[
i
]
)
instanceof
Button
)
{
Button
button
=
(
Button
)
convertView
.
findViewById
(
ItemId
[
i
]
)
;
button
.
setText
(
(
String
)
list
.
get
(
position
)
.
get
(
flag
[
i
]
)
)
;
button
.
setOnClickListener
(
new
Button
.
OnClickListener
(
)
{
@Override
public
void
onClick
(
View
v
)
{
new
AlertDialog
.
Builder
(
TestActivity
.
TestActivity
)
.
setTitle
(
"Button"
)
.
setMessage
(
"按钮触发监听事件!"
)
.
show
(
)
;
}
}
)
;
Log
.
e
(
"type"
,
"button"
)
;
}
else
if
(
convertView
.
findViewById
(
ItemId
[
i
]
)
instanceof
TextView
)
{
TextView
textView
=
(
TextView
)
convertView
.
findViewById
(
ItemId
[
i
]
)
;
textView
.
setText
(
(
String
)
list
.
get
(
position
)
.
get
(
flag
[
i
]
)
)
;
Log
.
e
(
"type"
,
"textview"
)
;
}
else
{
//预留其他控件处理,但必需写在TextView的前面
}
}
return
convertView
;
}
}
|
写主界面的TestActivity:
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
package
tabhost
.
demo
;
import
java
.
util
.
ArrayList
;
import
java
.
util
.
HashMap
;
import
java
.
util
.
List
;
import
java
.
util
.
Map
;
import
tabhost
.
demo
.
widget
.
ListSimpleAdapter
;
import
android
.
app
.
Activity
;
import
android
.
app
.
AlertDialog
;
import
android
.
os
.
Bundle
;
import
android
.
view
.
View
;
import
android
.
widget
.
AdapterView
;
import
android
.
widget
.
ListView
;
import
android
.
widget
.
AdapterView
.
OnItemClickListener
;
public
class
TestActivity
extends
Activity
{
private
ListSimpleAdapter
listAdapter
;
private
ListView
listView
;
// 声明列表视图对象
private
List
<
Map
<
String
,
Object
>>
list
;
// 声明列表容器
public
static
TestActivity
TestActivity
;
private
int
position_tmp
;
//position的临时存储变量
@Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
TestActivity
=
this
;
}
@Override
protected
void
onResume
(
)
{
super
.
onResume
(
)
;
//实例化列表视图
listView
=
new
ListView
(
this
)
;
//实例化列表容器
list
=
new
ArrayList
<
Map
<
String
,
Object
>>
(
)
;
try
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
//实例一个列表数据容器,并将数据库数据添加到列表容器,每一个map的数据对应ListView中完整的一项
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>
(
)
;
map
.
put
(
"pic"
,
R
.
drawable
.
ava
)
;
map
.
put
(
"title"
,
"你好,我是标题"
)
;
map
.
put
(
"content"
,
"测试内容,测试测试"
)
;
map
.
put
(
"button"
,
"按钮"
+
Integer
.
toString
(
i
)
)
;
list
.
add
(
map
)
;
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
)
;
}
//实例化适配器,具体可参见SimpleAdapter的使用
listAdapter
=
new
ListSimpleAdapter
(
this
,
list
,
R
.
layout
.
listsimpleadapter
,
new
String
[
]
{
"pic"
,
"title"
,
"content"
,
"button"
}
,
new
int
[
]
{
R
.
id
.
pic
,
R
.
id
.
title
,
R
.
id
.
content
,
R
.
id
.
button
}
)
;
listView
.
setAdapter
(
listAdapter
)
;
//添加ListView每一行的点击监听事件,此处可设置监听处理操作
listView
.
setOnItemClickListener
(
new
OnItemClickListener
(
)
{
public
void
onItemClick
(
AdapterView
<
?
>
arg0
,
View
arg1
,
int
position
,
long
id
)
{
position_tmp
=
position
;
new
AlertDialog
.
Builder
(
TestActivity
)
.
setTitle
(
"ListView"
)
.
setMessage
(
"你点击了第"
+
Integer
.
toString
(
position_tmp
)
+
"行!"
)
.
show
(
)
;
}
}
)
;
//显示列表视图
this
.
setContentView
(
listView
)
;
}
}
|
至此,一个ListView就做完了。与传统的ListView,代码具有很高的重用性和扩展性,并且能很容易实现一个ListView。
代码附件,在上一篇的基础上我将第一个标签改成了ListView。