在Android中使用ListActivity可以很方便的绑定一组数据或者一个查询。但是,使用过程中也会遇到一些问题。在此,我将自己遇到的问题以及解决方法记录下来,一方面做一个备忘,同时,也希望有缘人能少走弯路。
问题一: Listview中的Item数目到底是多少
ListView中的Item数目可以使用getCount方法获得,经过验证得到的结果是,其Item数目等于界面上显示的Item数目,这个数目可能小于实际上绑定的数据条目数。
那么,在实际中如果有额外的非绑定数据源的数据需要编辑保存的时候,如何才能保存他们呢?
解决该问题的方法是:自定义ListAdapter,在其中保存额外需要保存的数据。
问题二:在Item中添加CheckBox出现麻烦了
在item中添加Checkbox的时候不小心会遇到麻烦,可能出现的情况是:
(1)Listview不能相应点击事件
(2)Listview点击第一个Item的时候最后一个Item也出现点击事件(反之亦然)
以上两种情况是我实际遇到的bug,经过各种纠结和反复测试,出现问题的原因是CheckBox相应焦点、点击事件的优先级别比Listview要高,所以出现问题。
解决方法如下(和问题一一对应):
(1)将Checkbox设置focusable属性为false
(2)接着将CheckBox设置Clickable属性为false.
一下是本人程序片段,仅供参考:
1
|
<!-- ans_item.xml -->
|
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
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:padding
=
"10sp"
>
<
CheckBox
android:id
=
"@+id/ans_item_select"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_alignParentRight
=
"true"
android:focusable
=
"false"
android:clickable
=
"false"
android:checked
=
"false"
android:gravity
=
"center_vertical"
/>
<
RelativeLayout
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:layout_alignParentLeft
=
"true"
>
<
SPAN
style
=
"WHITE-SPACE: pre"
> </
SPAN
> ....
<
TextView
android:id
=
"@+id/ans_item_time"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_below
=
"@id/ans_item_locname"
android:layout_toRightOf
=
"@id/a4"
/>
</
RelativeLayout
>
</
RelativeLayout
>
|
1
|
|
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
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
<
PRE
class
=
brush
:java
name
=
"code"
>public class AnsList extends ListActivity {
private PoiDbAdapter dba = null;
private Cursor cursor = null;
private ListView listView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ans_list);
// 初始化标题
...
// 初始化列表
initList();</
PRE
><
PRE
class
=
brush
:java
name
=
"code"
> if (listView == null || listView.getCount() <
1
) {
findViewById(R.id.ans_foot).setVisibility(View.GONE);
} else {
initEvents();
}
}
/** 初始化列表 */
private void initList() {
listView
=
getListView
();
dba
=
new
PoiDbAdapter(this);
cursor
=
dba
.selectAnsByQnaire(QNaireBuilder.getQnaire(null)
.getQnaireId());
startManagingCursor(cursor);</PRE><
PRE
class
=
brush
:java
name
=
"code"
> // 构造游标适配器
MyCursorAdapter adapter = new MyCursorAdapter(this, R.layout.ans_item,
cursor, new String[] { ARemoteId, ALongi, ALati, ALocName,
ATime }, new int[] { R.id.ans_item_num,
R.id.ans_item_longi, R.id.ans_item_lati,
R.id.ans_item_locname, R.id.ans_item_time });
// 自定义ViewBinder,日期类型的数据需要转换
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
public boolean setViewValue(View view, Cursor cursor,
int columnIndex) {
String text = cursor.getString(columnIndex);
if (cursor.getColumnName(columnIndex).equalsIgnoreCase(ATime)) {
text = TimeTools.formatTime(Long.valueOf(text));
}
if (view instanceof TextView) {
((TextView) view).setText(text);
}
return true;
}
});</
PRE
><
PRE
class
=
brush
:java
name
=
"code"
> setListAdapter(adapter);</
PRE
><
PRE
class
=
brush
:java
name
=
"code"
> }
/** 为按钮和复选框添加事件处理, 为列表添加事件 */
private void initEvents() {
<
SPAN
style
=
"WHITE-SPACE: pre"
> </
SPAN
>....
((CheckBox) findViewById(R.id.ans_cbx_select))
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
selectAllOrNot(isChecked);
}
});
}
...
/** 全选或全部不选 */
protected void selectAllOrNot(boolean isChecked) {
int count = listView.getChildCount();
for (int i = 0; i <
count
; i++) {
((CheckBox) ((listView.getChildAt(i))
.findViewById(R.id.ans_item_select))).setChecked(isChecked);
}
((MyCursorAdapter) listView.getAdapter()).selectAll(isChecked);
}
...
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
CheckBox cbx = (CheckBox) v.findViewById(R.id.ans_item_select);
if (cbx != null) {
cbx.toggle();
((MyCursorAdapter) l.getAdapter())
.select(position, cbx.isChecked());
}
}
}
</PRE><
BR
>
// 自定义ListAdapter<
BR
>
public class MyCursorAdapter extends SimpleCursorAdapter {<
BR
>
<
PRE
class
=
brush
:html
name
=
"code"
><
PRE
class
=
brush
:java
name
=
"code"
> private HashMap<
Integer
, Boolean> isSelected = null;
public MyCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
isSelected = new HashMap<
Integer
, Boolean>();
selectAll(false);
}
</
PRE
><
PRE
class
=
brush
:java
name
=
"code"
><
SPAN
style
=
"WHITE-SPACE: pre"
> </
SPAN
>// ListView加载新的Item的时候会调用这个方法</
PRE
><
PRE
class
=
brush
:java
name
=
"code"
><
SPAN
style
=
"WHITE-SPACE: pre"
> </
SPAN
>// 在加载前设置好意境保存好的Checkbox的状态
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
Boolean b = isSelected.get(position);
if (null == b)
b = false;
if (convertView instanceof ViewGroup) {
ViewGroup g = (ViewGroup) convertView;
for (int i = 0; i <
g.getChildCount
(); i++) {
View
v
=
g
.getChildAt(i);
if (v instanceof CheckBox) {
((CheckBox) v).setChecked(b);
break;
}
}
}
return convertView;
}
public void select(int postion, boolean isChecked) {
isSelected.put(postion, isChecked);
}
public void selectAll(boolean isChecked) {
int
a
=
this
.getCount();
for (int
b
=
0
; b < a; b++) {
select(b, isChecked);
}
}
}
</PRE>
<
P
><
BR
>
</
P
>
<
PRE
></
PRE
>
<
PRE
></
PRE
>
</
PRE
>
|