天天看點

ListView 中的每一項添加一個checkbox複選框,實作複選功能

ListView 中的每一項添加一個checkbox複選框,實作複選功能。

包含ListView的布局檔案

ListView 中的每一項添加一個checkbox複選框,實作複選功能
<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>
           

清單每一項的布局

ListView 中的每一項添加一個checkbox複選框,實作複選功能

完整的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的狀态而不至于錯亂顯示問題。