论坛首页 移动开发技术论坛

ListView的bug解决,如果有checkbox的话,选中的值在翻屏时会跳来跳去

浏览 10543 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-07-20   最后修改:2011-07-20

废话不多说,直接上图上代码

翻屏前选择了2,3,4,5

翻屏后


 向上翻屏,选择的还是2,3,4,5

 

其实就是红色的地方是关键点,用了一个集合来保存cb的选择状态,其它的关于viewHolder和和inflate的布局什么就不说了

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class ListViewCheckboxActivity extends Activity implements OnCheckedChangeListener {

	private ListView listView;
	private List<Map<String, Object>> list;
	private CheckBox cball;
	ListViewAdapter adapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		listView = (ListView) findViewById(R.id.lv);
		cball = (CheckBox) findViewById(R.id.cball);
		cball.setOnCheckedChangeListener(this);//全选
		
		list = buildList();
		adapter = new ListViewAdapter(this, list);
		listView.setAdapter(adapter);
	}

	private List<Map<String, Object>> buildList() {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		for (int i = 0; i < 20; i++) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("icon", R.drawable.icon);
			map.put("title", "主题" + (i + 1));
			list.add(map);
		}
		return list;
	}

	class ListViewAdapter extends BaseAdapter {
		private Context context;
		private List<Map<String, Object>> list;
		private LayoutInflater inflater;
		private List<Boolean> checkBoxesStatus;

		
		public ListViewAdapter(Context context, List<Map<String, Object>> list) {
			super();
			this.context = context;
			this.list = list;
			int listsize = list.size();
			checkBoxesStatus = new ArrayList<Boolean>(listsize);
			for(int i = 0;i<list.size();i++){
				checkBoxesStatus.add(false);
			}
			this.inflater = LayoutInflater.from(context);
		}

		public List<Map<String, Object>> getList() {
			return list;
		}
		public List<Boolean> getCheckBoxesStatus() {
			return checkBoxesStatus;
		}
		@Override
		public int getCount() {
			return list.size();
		}

		@Override
		public Object getItem(int position) {
			return list.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(final int position, View convertView, ViewGroup parent) {
			
			ViewHolder viewHolder = null;
			Map<String, Object> map = list.get(position);
			Boolean checkBoxStatus = checkBoxesStatus.get(position);
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.list_item, null);
				viewHolder = new ViewHolder();
				viewHolder.img = (ImageView) convertView.findViewById(R.id.icon);
				viewHolder.tv = (TextView) convertView.findViewById(R.id.title);
				viewHolder.cb = (CheckBox) convertView.findViewById(R.id.cb);
				convertView.setTag(viewHolder);
			}else{
				viewHolder = (ViewHolder) convertView.getTag();
			}
			
			viewHolder.img.setImageResource((Integer) map.get("icon"));
			viewHolder.tv.setText((String) map.get("title"));
			
			viewHolder.cb.setId(position);
			viewHolder.cb.setChecked(checkBoxStatus);
			viewHolder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
				@Override
				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
					checkBoxesStatus.set(buttonView.getId(), isChecked);
					notifyDataSetChanged();
				}
			});
			return convertView;
		}
	}
	
	static class ViewHolder {
		private ImageView img;
		private TextView tv;
		private CheckBox cb;
	}

	@Override
	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
		List<Boolean> checkBoxesStatus = adapter.getCheckBoxesStatus();
		for(int i = 0;i<list.size();i++){
			checkBoxesStatus.set(i, isChecked);
		}
		adapter.notifyDataSetChanged();
	}
 

 

  • 大小: 67.4 KB
  • 大小: 70 KB
  • 大小: 67.2 KB
   发表时间:2011-07-20  
这个第二个编辑模式不太会用啊,明明加了颜色,杂出来得是代码没颜色效果喃,还得研究研究
0 请登录后投票
   发表时间:2011-07-21  
我也遇到了,用类类似的方法,用List保存了 check的 cb 在getView里面去判断,如果cb在list中,就设置为选中,否则不选中。在onCheckedChanged中选中则添加到list中,否则移除
0 请登录后投票
   发表时间:2011-07-21  
我也是这么做的,只不过总觉得这么干有点浪费,不知道还有什么好方法没有。
www.91dota.com
0 请登录后投票
   发表时间:2011-07-22  
这个不属于Android ListView的bug

ListView里的View都只能是无状态的,在Adapter的getView方法里给View附上相应的状态

这样可以保证ListView的高效性也减少了内存的开销,建议去看下ListView的源码
0 请登录后投票
   发表时间:2011-07-22  
这个的确不是bug,Item显示什么,完全是你给予他什么值,在他复用的时候你没更新状态,还赖他不正确显示。
0 请登录后投票
   发表时间:2011-07-22  
非bug,之前也遇到过,zhuixinjian正解
0 请登录后投票
   发表时间:2011-07-22  
谢谢大家,是我描述不正确,因为在这个多选的时候,没达到自己想要的效果。晚上一定看看源码。android我也才接触,有理解错误的地方,还枉多指教,3q。
0 请登录后投票
   发表时间:2011-07-25  
这个我去年刚进公司做android就会了
还帮公司解决全选这问题
0 请登录后投票
   发表时间:2011-07-25  
qx8668 写道
这个我去年刚进公司做android就会了
还帮公司解决全选这问题

呵呵,互相学习,这个小demo全选实现了的
0 请登录后投票
论坛首页 移动开发技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics