Android中使用ListView以及在Listview中添加CheckBox时若干问题

 

在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" ?>
< RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     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 >
  
          
                 < DIV >来源:http://blog.csdn.net/whucyl/article/details/7341133</ DIV >
              
         </ PRE >

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值