Android开发:实现带checkbox的listview

项目要用到一个listview,要求是可以显示图片,后面还有有复选框。

先新建一个MyAdapter类,继承自BaseAdapter。在MyAdapter中实现对数据的绑定,我这儿由于是测试的,所以把数据写死了。

package com.zwq.umeng;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
import android.content.Context;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.BaseAdapter;  
import android.widget.CheckBox;  
import android.widget.ImageView;  
import android.widget.TextView;  
public class MyAdapter extends BaseAdapter {  
    private LayoutInflater mInflater;  
    private List<Map<String, Object>> mData;  
    public static Map<Integer, Boolean> isSelected;  
    public MyAdapter(Context context) {  
        mInflater = LayoutInflater.from(context);  
        init();  
    }  
    //初始化  
    private void init() {  
        mData=new ArrayList<Map<String, Object>>();  
        for (int i = 0; i < 5; i++) {  
            Map<String, Object> map = new HashMap<String, Object>();  
            map.put("img", R.drawable.icon);  
            map.put("title", "第" + (i + 1) + "行的标题");  
            mData.add(map);  
        }  
        //这儿定义isSelected这个map是记录每个listitem的状态,初始状态全部为false。  
        isSelected = new HashMap<Integer, Boolean>();  
        for (int i = 0; i < mData.size(); i++) {  
            isSelected.put(i, false);  
        }  
    }  
    @Override  
    public int getCount() {  
        return mData.size();  
    }  
    @Override  
    public Object getItem(int position) {  
        return null;  
    }  
    @Override  
    public long getItemId(int position) {  
        return 0;  
    }  
    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        ViewHolder holder = null;  
        //convertView为null的时候初始化convertView。  
        if (convertView == null) {  
            holder = new ViewHolder();  
            convertView = mInflater.inflate(R.layout.vlist, null);  
            holder.img = (ImageView) convertView.findViewById(R.id.img);  
            holder.title = (TextView) convertView.findViewById(R.id.title);  
            holder.cBox = (CheckBox) convertView.findViewById(R.id.cb);  
            convertView.setTag(holder);  
        } else {  
            holder = (ViewHolder) convertView.getTag();  
        }  
        holder.img.setBackgroundResource((Integer) mData.get(position).get(  
                "img"));  
        holder.title.setText(mData.get(position).get("title").toString());  
        holder.cBox.setChecked(isSelected.get(position));  
        return convertView;  
    }  
    public final class ViewHolder {  
        public ImageView img;  
        public TextView title;  
        public CheckBox cBox;  
    }  
}

上面类中要注意getView()方法中对数据的处理。

接下要新建一个list.xml文件,这个就是布局image、textview、checkbox。

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="horizontal"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
    <ImageView  
        android:id="@+id/img"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_gravity="center_vertical"/>  
    <TextView   
        android:id="@+id/title"  
        android:textSize="18dip"  
        android:layout_weight="1"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"/>  
    <CheckBox  
        android:id="@+id/cb"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:focusable="false"  
        android:focusableInTouchMode="false"  
        android:clickable="false"         
        android:checkMark="?android:attr/listChoiceIndicatorMultiple"/>  
</LinearLayout>

android:layout_weight="1"这一句可以使中间的textview权重增大,从而后面的checkbok可以居右显示。

android:focusable="false" 
        android:focusableInTouchMode="false" 
        android:clickable="false"

这三句很重要,如果不加就会出现错误。

由于checkbox的点击事件优先级比listview的高,所以要在checkbox中添加android:focusable="false",使得checkbox初始的时候没有获取焦点。

接下来在main.xml中添加Listview组件

<ListView  
        android:id="@+id/lv"  
        android:layout_width="fill_parent"   
        android:layout_height="wrap_content"/>

接下来就是在activity中调用:

list=(ListView)findViewById(R.id.lv);  
        MyAdapter adapter=new MyAdapter(this);  
        list.setAdapter(adapter);  
        list.setItemsCanFocus(false);  
        list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);  
        list.setOnItemClickListener(new OnItemClickListener(){  
            @Override  
            public void onItemClick(AdapterView<?> parent, View view,  
                    int position, long id) {  
                ViewHolder vHollder = (ViewHolder) view.getTag();  
//在每次获取点击的item时将对于的checkbox状态改变,同时修改map的值。  
                vHollder.cBox.toggle();  
                MyAdapter.isSelected.put(position, vHollder.cBox.isChecked());  
            }  
        });

最新看一下效果图:

效果图

要获取哪些项目被选择了,可以这样测试:

OnClickListener bPop = new OnClickListener() {  
        @Override  
        public void onClick(View v) {  
            for(int i=0;i<list.getCount();i++){  
                if(MyAdapter.isSelected.get(i)){  
                    ViewHolder vHollder = (ViewHolder) list.getChildAt(i).getTag();  
Log.i(TAG, "--onClick --"+vHollder.title.getText());  
                }  
            }  
        }  
    };