很多时候我们需要在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>