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));  <span style="font-family: Arial, Helvetica, sans-serif;">// 用一個HashMap對象來存儲CheckBox的點擊狀態,每次調用getView都要這樣手動設置狀態</span>
		
		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的監聽器

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:clickable="false"
        android:text="CheckBox"
        android:textSize="30sp" />






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章