Android ListView与CheckBox

在Android开发中,有时需要把CheckBox放在ListView的item中。在继承BaseAdapter创建自己的适配器时,由于View重用以及CheckBox无法自动保存状态的问题,需要在getView函数中手动设置CheckBox的点击状态,否则CheckBox默认不点击,当CheckBox所在的item离开屏幕时,其点击状态便会消失,下次重用View时又恢复到默认状态。

	@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		ViewHolder viewHolder = new ViewHolder();
		if (convertView == null) {
			convertView = layoutInflater.inflate(R.layout.listview_item, null);
			viewHolder.checkBox = (CheckBox) convertView
					.findViewById(R.id.checkBox);
			convertView.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) convertView.getTag();  
		}

		viewHolder.checkBox.setChecked(isSelectedMap.get(position));  // 用一个HashMap对象来存储CheckBox的点击状态,每次调用getView都要这样手动设置状态
		
		viewHolder.checkBox.setOnClickListener(new OnClickListener() {   // 这里为CheckBox添加监听器
			
			@Override
			public void onClick(View v) {
				boolean isChecked = 
						!isSelectedMap.get(position);   // 由于匿名内部类无法使用局部变量,因此在getView的参数中,需要把position设为final。
				((CheckBox)v).setChecked(isChecked);
				isSelectedMap.put(position, isChecked);  // 一旦CheckBox被点击,isSelectedMap中的状态就要修改
			}
		});
		
		return convertView;
	}


可能遇到的问题:

一、

由于匿名内部类无法使用局部变量,初学者可能会在MyAdapter(即getView所在的类)中使用成员变量pos来等效代替这里的position,如果在getView函数中让pos=position,再把pos传进匿名内部类,结果会出错。因为getView是系统自己调用的,如果你的列表视图滚到item8,系统会调用getView,传进的参数position==8,此时pos的值被设为8,这时无论你点击哪个CheckBox,都只会保存第8个CheckBox的状态,而其他控件只是呈现点击的假象,并没有将状态存到isSelectedMap中,下次刷新视图时,状态跟之前isSelectedMap中保存的状态相同。

二、

如果手动设置CheckBox状态时调用了setCheck函数,则CheckBox的监听器要选择OnClickListener,而不能是OnCheckedChangeListener。查阅源码可以知道,setCheck函数调用了OnCheckedChangeListener的回调函数,而监听器的回调函数是用来保存点击状态。当系统调用getView时,在setCheck语句这里会修改isSelectedMap。


如果想在ListView里设置监听器,则需要把CheckBox的焦点传给ListView

		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView parent, View view,
					int position, long id) {
				ViewHolder viewHolder = (ViewHolder) view.getTag();  // 这里的view等价于getView函数中的convertView
				viewHolder.checkBox.toggle();   // 点击item时,更改CheckBox的状态
				isSelectedMap.put(position, viewHolder.checkBox.isChecked());  // 保存状态
				myAdapter.notifyDataSetChanged();  // 通知适配器状态已经改变
			}
		});
同时XML文件要将CheckBox的焦点传回ListView,并取消CheckBox的监听器

    






你可能感兴趣的:(Android)