很多時候我們需要在ListView中放置checkbox控件,這時候我們可能會想到用simpleAdapter,但是simpleAdapter的getChildAt()方法有個問題:當listview的數目很多時,listview需要滾動,這時候第一個選中的,最後一個也會一起選中。這是由於getChildAt()只能獲取當前可視的區域的ViewGroup。因此,我們需要使用自定義的BaseAdapter.
BaseAdapter上一篇博客已經介紹過了,而這篇着重在於如何在BaseAdapter中實現完美的checkbox的單選,多選,取消功能。
首先有個問題我們需要注意一下:checkbox的點擊事件優先級高於listview,因此我們需要屏蔽掉checkbox的優先級,在XML文件中編寫代碼如下:
android:focusable="false" //設置不獲取焦點
android:clickable="false"//設置不可點擊
其次,我們需要將每個checkbox的點擊狀態保存起來,這裏使用isSelected這個HashMap<Integer,Boolean>對象來存儲相應位置處的checkbox的狀態.
先來看看實際的運行圖:
以下爲程序Activity的代碼:
public class MainActivity extends Activity {
private List<Map<String,Object>> listItems;
private ListView listView;
private String[] header={"姓名","性別","電話","住址","姓名","性別","電話","住址"};
private String[] content={"張三","男","18850201111","中南海","張三","男","18850201111","中南海"};
private MyBaseAdapter adapter;
private Button allselect_bn;
private Button allcancel_bn;
private static HashMap<Integer, Boolean> isSelected=new HashMap<Integer, Boolean>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listItems=new ArrayList<Map<String,Object>>();
listItems=getListItems();
listView=(ListView) findViewById(R.id.listview);
allselect_bn=(Button)findViewById(R.id.allselect_bn);
allcancel_bn=(Button)findViewById(R.id.allcancel_bn);
allselect_bn.setOnClickListener(new AllSelectListener());
allcancel_bn.setOnClickListener(new AllCancelListener());
adapter=new MyBaseAdapter(this);
adapter.setIsSelected(isSelected);//設置isSelected map對象
//初始化isSelected
for(int i=0;i<header.length;i++){
adapter.getIsSelected().put(i, true);
System.out.println(adapter.getIsSelected().get(i));
};
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
ViewHolder holder=(ViewHolder)view.getTag();
holder.checkbox.toggle();
System.out.println("第幾條item"+position+"狀態"+holder.checkbox.isChecked());
adapter.getIsSelected().put(position, holder.checkbox.isChecked());
}
});
}
public class AllSelectListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
for(int i=0;i<header.length;i++){
adapter.getIsSelected().put(i, true);
}
adapter.notifyDataSetChanged();
}
}
public class AllCancelListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
for(int i=0;i<header.length;i++){
adapter.getIsSelected().put(i, false);
}
adapter.notifyDataSetChanged();
}
}
private List<Map<String, Object>> getListItems()
{
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map;
for(int i=0;i<header.length;i++)
{
map = new HashMap<String, Object>();
map.put("header", header[i]);
map.put("content", content[i]);
list.add(map);
}
return list;
}
public static class ViewHolder
{
public TextView title;
public TextView info;
public CheckBox checkbox;
}
public class MyBaseAdapter extends BaseAdapter {
private LayoutInflater inflater;
private HashMap<Integer, Boolean> isSelected;
/**************構造方法獲取上下文********************************/
private MyBaseAdapter(Context context){
this.inflater=LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return listItems.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return listItems.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder=null;
if(convertView==null){
holder=new ViewHolder();
convertView=inflater.inflate(R.layout.task_item, null);
holder.title=(TextView) convertView.findViewById(R.id.nameheader);
holder.info=(TextView) convertView.findViewById(R.id.content);
holder.checkbox=(CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
}
else
holder=(ViewHolder) convertView.getTag();
/*********以下設置控件顯示內容***********/
holder.title.setText((String) listItems.get(position).get("header"));
holder.info.setText((String) listItems.get(position).get("content"));
System.out.println("getlistview"+getIsSelected().get(position));
holder.checkbox.setChecked(getIsSelected().get(position));//根據checkbox是否被選擇設置勾選
//get(position)可以獲取當前position的checkbox map裏對應的布爾變量
return convertView;
}
public HashMap<Integer,Boolean> getIsSelected(){
return isSelected;
}
public void setIsSelected(HashMap<Integer, Boolean> isSelected){
this.isSelected=isSelected;
}
}
}
以下爲XML佈局文件的代碼:
1.activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="200dp"></ListView>
<Button
android:id="@+id/allselect_bn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="全選"/>
<Button
android:id="@+id/allcancel_bn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="取消" />
</LinearLayout>
2.task_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
>
<TextView android:id="@+id/nameheader"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_marginLeft="10dp"
android:textSize="15dp"
android:textColor="#000000"
android:layout_weight="1"
/>
<TextView android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_marginLeft="50dp"
android:textSize="15dp"
android:textColor="#000000"
android:layout_weight="1"
/>
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false"
></CheckBox>
</LinearLayout>