ListView 中的每一项添加一个checkbox复选框,实现复选功能

本文介绍如何在Android的ListView中为每一项添加checkbox,并实现复选功能。通过自定义Adapter,使用Set保存选中项的ID,配合getView方法更新checkbox状态。还展示了全选功能的实现,通过回调函数在Activity中更新Adapter界面。

ListView 中的每一项添加一个checkbox复选框,实现复选功能。
包含ListView的布局文件
这里写图片描述

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".RecvLoadActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingBottom="@dimen/activity_load_mian_paddingBotton">

            <CheckBox
                android:id="@+id/cbFcrq"
                android:checked="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="发车日期:" />

            <EditText
                android:id="@+id/etFcrq"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center_horizontal"
                android:hint="格式 2015-8-8"
                android:inputType="date"
                android:singleLine="true" />

            <TextView
                android:id="@+id/btnGetDate"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="@drawable/button_normal_bg_selector"
                android:gravity="center_vertical"
                android:text="选择"
                android:textColor="@color/white" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingBottom="@dimen/activity_load_mian_paddingBotton">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="车  牌  号:" />

            <EditText
                android:id="@+id/etLoadCph"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center_horizontal"
                android:hint="例如输入2352再选择"
                android:singleLine="true" />

            <TextView
                android:id="@+id/btnSelectCar"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="@drawable/button_normal_bg_selector"
                android:gravity="center_vertical"
                android:text="选择"
                android:textColor="@color/white" />
        </LinearLayout>
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/lightgray" />
    </LinearLayout>
    <ListView
        android:id="@+id/listViewLoad"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:dividerHeight="1px"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:background="@color/gray"
        android:layout_height="wrap_content">
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/blue" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:paddingRight="6dp"
            android:paddingLeft="6dp"
            android:orientation="horizontal"
            >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下一接驳网点:" />
            <Spinner
                android:id="@+id/spinnerNextNet"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/lightgray" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingRight="6dp"
            android:paddingLeft="6dp"
            android:orientation="horizontal">
            <Button
                android:id="@+id/btnQuery"
                style="@style/Widget.AppCompat.Button.Borderless"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/button_bottom_bg_selector"
                android:text="查询"
                android:textColor="@color/blue"
                />
            <Button
                android:id="@+id/btnRecvLoad"
                style="@style/Widget.AppCompat.Button.Borderless"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:background="@drawable/button_bottom_bg_selector"
                android:gravity="center"
                android:layout_weight="1"
                android:text="接收并快捷装车"
                android:textColor="@color/blue"
                android:textSize="18sp"
                android:textStyle="bold" />
            <TextView
                android:id="@+id/tvTotalCount"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:text="0"
                android:textSize="17sp"
                android:textColor="#F00"/>
            <CheckBox
                android:id="@+id/cbAll"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:text="全选"
                android:gravity="center_vertical"
                />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

列表每一项的布局
这里写图片描述
完整的item.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:baselineAligned="false"
    android:padding="4dp" >

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical" >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            >
            <TextView
                android:id="@+id/tvBillNo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="运单号aaaaaaaaaa"
                android:textColor="#F00"
                android:textStyle="bold" />
            <TextView
                android:id="@+id/tvBillFlowStatus"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:text="流转状态"
                android:gravity="center"
                android:layout_weight="1"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/tvTerminal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="end"
                android:text="目的地" />

        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingTop="2dp" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="发车:"
                android:textStyle="bold"
                />

            <TextView
                android:id="@+id/tvDepartTime"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="2015-08-31 10:45" />
            <TextView
                android:id="@+id/tvCph"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:text="车牌12345"
                android:gravity="center"
                android:layout_weight="1"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:textStyle="bold" />
            <TextView
                android:id="@+id/tvCalcCount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="end"
                android:text="件数" />
        </LinearLayout>


    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical" >
        <CheckBox
            android:padding="6dp"
            android:id="@+id/cbItem"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center_vertical" />
    </LinearLayout>
</LinearLayout>

核心的Adapter继承BaseAdapter

public class RecvLoadAdapter extends BaseAdapter {
    private OnItemCheckListener mOnItemCheckListener;
    private List<Bill> mList;
    private LayoutInflater mInflater;
    public Set<Long> mCheckedSet = new HashSet<>();//保存逻辑运单id,此集合用来指示勾选框的状态逻辑
    public RecvLoadAdapter(Context context,OnItemCheckListener onItemCheckListener, List<Bill> data){
        mOnItemCheckListener = onItemCheckListener;
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mList = data;
    }
    @Override
    public int getCount() {
        return mList.size();
    }
    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v ;
        if(convertView == null){
            v = mInflater.inflate(R.layout.item_recv_load,parent,false);
        }else{
            v = convertView;
        }
        //填充view
        Bill item = (Bill) getItem(position);
        String date = item.getL_DepartDate();
        if(date!=null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.getDefault());
            try {
                String fcsj = sdf.format(sdf.parse(date))+" "+item.getL_DepartTime();
                ((TextView)v.findViewById(R.id.tvDepartTime)).setText(fcsj);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        ((TextView)v.findViewById(R.id.tvTerminal)).setText(item.getB_Terminal());
        ((TextView)v.findViewById(R.id.tvCalcCount)).setText(String.format(Locale.getDefault(),"%d件",item.getB_CalcCount()));
        ((TextView)v.findViewById(R.id.tvBillNo)).setText(item.getB_No());
        ((TextView)v.findViewById(R.id.tvCph)).setText(item.getL_CarPlateNo());
        ((TextView)v.findViewById(R.id.tvBillFlowStatus)).setText(item.getB_FlowStatusText());
        //添加删除按钮点击事件
        //final int p = position;
        final long p = item.getBillId();
        CheckBox cbItem =  v.findViewById(R.id.cbItem);
        cbItem.setChecked(mCheckedSet.contains(p));
        cbItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mCheckedSet.contains(p)){
                    mCheckedSet.remove(p);
                    mOnItemCheckListener.onItemCheckClick(p,false);//unchecked事件
                }else{
                    mCheckedSet.add(p);
                    mOnItemCheckListener.onItemCheckClick(p,true);//checked事件
                }
            }
        });
        return v;
    }
    /**
     * 当主界面点击全选按钮时触发
     * @param isChecked
     */
    public void onCheckAllClick(boolean isChecked){
        if(isChecked){
            for(Bill b: mList){
                mCheckedSet.add(b.getBillId());
            }
        }else{
            mCheckedSet.clear();
        }
        notifyDataSetChanged();
    }
    public interface OnItemCheckListener{
        /**
         * 某一项复选框check事件
         * @param id bill ID
         * @param checked true表示选中事件,false表示不选中事件
         */
        void onItemCheckClick(long id,boolean checked);
    }
}

使用ListView的Fragment或者Activity


public class RecvLoadActivity extends Activity implements RecvLoadAdapter.OnItemCheckListener {
    private CheckBox cbFcrq,cbAll;
    private ListView mListView;
    private List<Bill> mList;
    private RecvLoadAdapter mAdapter;
    private TextView tvTotalCount;//已checked的数量
    private View btnQuery;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recv_load);        
        //初始化列表
        mList = new ArrayList<>();
        mAdapter = new RecvLoadAdapter(this,this,mList);
        mListView.setAdapter(mAdapter);
        //全选
        cbAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean isChecked = cbAll.isChecked();
                mAdapter.onCheckAllClick(isChecked);
                tvTotalCount.setText(String.valueOf(mAdapter.mCheckedSet.size() ));
            }
        });
    }
    //单击某项,勾选之
    @Override
    public void onItemCheckClick(long id, boolean checked) {
        if (checked) {
            if (mAdapter.mCheckedSet.size() == mList.size()) {
                cbAll.setChecked(true);
            }
        } else {
            cbAll.setChecked(false);
        }
        tvTotalCount.setText(String.valueOf( mAdapter.mCheckedSet.size()));
    }

核心的实现思路:在Adapter中用一个Set保存每个勾选的项的ID(最好用填充每个项的对象的唯一标识),在getView()方法中,关键的几何实现代码如下:

        final long p = item.getBillId();
        CheckBox cbItem = (CheckBox) v.findViewById(R.id.cbItem);
        cbItem.setChecked(mCheckedSet.contains(p));
        cbItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mCheckedSet.contains(p)){
                    mCheckedSet.remove(p);
                    mOnItemCheckListener.onItemCheckClick(p,false);//unchecked事件
                }else{
                    mCheckedSet.add(p);
                    mOnItemCheckListener.onItemCheckClick(p,true);//checked事件
                }
            }
        });
    请勿使用changeListener。
    mOnItemCheckListener 是回调接口,用于在Ativity中同步保存数据。

在Activity中实现全选复选框功能:

//全选
        cbAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean isChecked = cbAll.isChecked();
                mAdapter.onCheckAllClick(isChecked);
                tvTotalCount.setText(String.valueOf(mAdapter.mCheckedSet.size() ));
            }
        });

这里也用到了回调函数onCheckAllClick,该函数在Adapter中声明为public即可,当主界面点击全选按钮时更新Adapter界面:

public void onCheckAllClick(boolean isChecked){
        if(isChecked){
            for(Bill b: mList){
                mCheckedSet.add(b.getBillId());
            }
        }else{
            mCheckedSet.clear();
        }
        notifyDataSetChanged();
    }

总结:最关键的地方是用了一个Set来保存已checked的项,用于在getView重绘时正确标识checkbox的状态而不至于错乱显示问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值