ListView 的Item状态改变和保存

以前没发现的问题,使用ListView存放数据显示时,一般情况下使用时没问题,但是如果需要在ListView中的子控件改变状态时就出现问题了

看图, 选中了第1,2个,然后向下滚动,出现了没有选中的Item也被选中了,这样问题就出现了,每次改变状态时,在未知的地方也随机变化了?

        

MainActivity

 1 package com.example.listviewscrollstatus;
 2 
 3 import java.util.ArrayList;
 4 import java.util.HashMap;
 5 import java.util.List;
 6 import java.util.Map;
 7 
 8 import android.app.Activity;
 9 import android.os.Bundle;
10 import android.widget.ListView;
11 
12 public class MainActivity extends Activity {
13 
14     ListView listView;
15 
16     // 模拟数据源
17     int[] iconRes = { R.drawable.ic_launcher, R.drawable.ic_add, R.drawable.ic_add_selected };
18 
19     // 存放数据
20     private List<Map<String, Object>> dataList;
21 
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_main);
26 
27         initListView();
28     }
29 
30     private void initListView() {
31         listView = (ListView) findViewById(android.R.id.list);
32         getData();
33 
34         listView.setAdapter(new ListContentAdapter(this, dataList));
35     }
36 
37     private void getData() {
38 
39         dataList = new ArrayList<Map<String, Object>>();
40         Map<String, Object> map;
41         // 模拟数据,放入对应的logo icon,title,set icon
42         for (int i = 0; i < 40; i++) {
43             map = new HashMap<String, Object>();
44             map.put("icon", iconRes[i % 3]); // 轮流使用
45             map.put("title", "文字标题__" + i);
46             // map.put("set", "");
47 
48             dataList.add(map);
49             map = null;
50         }
51     }
52 
53 }
View Code

Adapter

 1 /**
 2  * 
 3  */
 4 package com.example.listviewscrollstatus;
 5 
 6 import java.util.List;
 7 import java.util.Map;
 8 
 9 import android.content.Context;
10 import android.view.LayoutInflater;
11 import android.view.View;
12 import android.view.ViewGroup;
13 import android.widget.BaseAdapter;
14 import android.widget.CheckBox;
15 import android.widget.ImageButton;
16 import android.widget.ImageView;
17 import android.widget.TextView;
18 
19 /**
20  * @Description
21  * @author act262
22  * @version 1.0
23  * @since 2014-6-21 下午5:58:38
24  * 
25  */
26 public final class ListContentAdapter extends BaseAdapter {
27     private Context mContext;
28     private List<Map<String, Object>> mList;
29     private ViewHolder viewHolder = null;
30 
31     public ListContentAdapter(Context context, List<Map<String, Object>> list) {
32         this.mContext = context;
33         this.mList = list;
34     }
35 
36     // 在绘制ListView时调用该方法
37     @Override
38     public int getCount() {
39         return mList.size();
40     }
41 
42     // 返回指定位置的Item
43     @Override
44     public Object getItem(int position) {
45         return mList.get(position);
46     }
47 
48     // 不指定id,一般为当前的位置
49     @Override
50     public long getItemId(int position) {
51         return position;
52     }
53 
54     /**
55      * 自定义Adapter的最重要的方法: 使用ViewHolder作为一个缓存的对象,可以减少findViewById();
56      * 假设一个ListView的空间一次加载10个item,也就是有对应的View
57      * 容器ConvertView10个,每次使viewHolder指向该ConvertView,第一个加载时convertView
58      * 为null,以后就不是null了; 当滚动ListView时,convertView不为null,从viewholder获取到缓存的视图数据,
59      */
60     @Override
61     public View getView(int position, View convertView, ViewGroup parent) {
62 
63         if (null == convertView) {
64             convertView = LayoutInflater.from(mContext).inflate(R.layout.view_listview_item, null);
65 
66             viewHolder = new ViewHolder();
67             viewHolder.iconView = (ImageView) convertView.findViewById(R.id.iv_icon);
68             viewHolder.titleView = (TextView) convertView.findViewById(R.id.tv_title);
69             viewHolder.selectView = (CheckBox) convertView.findViewById(R.id.cb_select);
70             viewHolder.setButton = (ImageButton) convertView.findViewById(R.id.ib_set);
71 
72             convertView.setTag(viewHolder);
73         } else {
74             viewHolder = (ViewHolder) convertView.getTag();
75         }
76 
77         viewHolder.iconView.setImageResource((Integer) mList.get(position).get("icon"));
78         viewHolder.titleView.setText((CharSequence) mList.get(position).get("title"));
79         // viewHolder.selectView.setChecked(checked);
80         // viewHolder.selectView.setBackgroundResource();
81 
82         return convertView;
83     }
84 
85     private final class ViewHolder {
86         ImageView iconView;
87         TextView titleView;
88         CheckBox selectView;
89         ImageButton setButton;
90     }
91 
92 }
View Code

 

 

为了实现能够保留住当前的状态,需要使用记录来处理

 1     // 用户记住CheckBox的状态
 2     private Map<Integer, Boolean> selectStaus;
 3 
 4     public ListContentAdapter(Context context, List<Map<String, Object>> list) {
 5         this.mContext = context;
 6         this.mList = list;
 7 
 8         selectStaus = new HashMap<Integer, Boolean>();
 9         // 初始状态全部为不选中状态,故设为false
10         for (int i = 0; i < list.size(); i++) {
11             // 使用当前的位置作为key,boolean作为value
12             selectStaus.put(i, false);
13         }
14     }

在getView中加上后就能记住listview下的某个子控件的状态了。

 1 viewHolder.selectView.setChecked(selectStaus.get(position));
 2 
 3         viewHolder.selectView.setOnClickListener(new OnClickListener() {
 4 
 5             @Override
 6             public void onClick(View v) {
 7                 // 记录状态改变了
 8                 selectStaus.put(position, viewHolder.selectView.isChecked());
 9             }
10         });

 

 

 最后附上工程Demo

 

posted @ 2014-06-21 18:10  act262  阅读(1073)  评论(0编辑  收藏  举报