android UI进阶之实现listview中checkbox的多选与记录

ListView的操作就一定会涉及到item和Adapter,我们还是先来实现这部分内容。

首先,写个item的xml布局,里面放置一个TextView和一个CheckBox。要注意的时候,这里我设置了CheckBox没有焦点,这样的话,无法单独点击checkbox,而是在点击listview的条目后,Checkbox会响应操作。


01 xml version="1.0"encoding="utf-8"?>
02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03     android:layout_width="fill_parent"
04     android:layout_height="fill_parent"
05     android:orientation="horizontal">
06     <TextView
07         android:id="@+id/item_tv"
08         android:layout_width="0dp"
09         android:layout_height="wrap_content"
10         android:layout_weight="1"
11         android:gravity="center_vertical"
12          />
13     <CheckBox
14         android:id="@+id/item_cb"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:clickable="false"
18         android:focusable="false"
19         android:focusableInTouchMode="false"
20         android:gravity="center_vertical"
21         />
22 LinearLayout>

下面就写一个Adapter类,我们依然继承BaseAdapter类。这里我们使用一个HashMap的键值来记录checkbox在对应位置的选中状况,这是本例的实现的基础。
01 publicclass MyAdapter extendsBaseAdapter{
02     // 填充数据的list
03     privateArrayList list;
04     // 用来控制CheckBox的选中状况
05     privatestatic HashMap isSelected;
06     // 上下文
07     privateContext context;
08     // 用来导入布局
09     privateLayoutInflater inflater = null;
10     // 构造器
11     publicMyAdapter(ArrayList list, Context context) {
12         this.context = context;
13         this.list = list;
14         inflater = LayoutInflater.from(context);
15         isSelected = newHashMap();
16         // 初始化数据
17         initDate();
18     }
19     // 初始化isSelected的数据
20     privatevoid initDate(){
21         for(inti=0; i            getIsSelected().put(i,false);
22         }
23     }
24     @Override
25     publicint getCount() {
26         returnlist.size();
27     }
28     @Override
29     publicObject getItem(intposition) {
30         returnlist.get(position);
31     }
32     @Override
33     publiclong getItemId(intposition) {
34         returnposition;
35     }
36     @Override
37     publicView getView(intposition, View convertView, ViewGroup parent) {
38         ViewHolder holder = null;
39             if(convertView == null) {
40             // 获得ViewHolder对象
41             holder = newViewHolder();
42             // 导入布局并赋值给convertview
43             convertView = inflater.inflate(R.layout.listviewitem, null);
44             holder.tv = (TextView) convertView.findViewById(R.id.item_tv);
45             holder.cb = (CheckBox) convertView.findViewById(R.id.item_cb);
46             // 为view设置标签
47             convertView.setTag(holder);
48         }else{
49             // 取出holder
50             holder = (ViewHolder) convertView.getTag();
51             }
52         // 设置list中TextView的显示
53         holder.tv.setText(list.get(position));
54         // 根据isSelected来设置checkbox的选中状况
55         holder.cb.setChecked(getIsSelected().get(position));
56         returnconvertView;
57     }
58     publicstatic HashMap getIsSelected() {
59         returnisSelected;
60     }
61     publicstatic void setIsSelected(HashMap isSelected) {
62         MyAdapter.isSelected = isSelected;
63     }
64 }

注释已经写的非常详尽了,通过
1 holder.cb.setChecked(getIsSelected().get(position));

这行代码我们实现了设置CheckBox的选中状况。

那么我们只需要在点击事件中,控制isSelected的键值即可控制对应位置checkbox的选中了。

在Activity中我们除了放置一个ListView外,还放置了三个按钮,分别实现全选,取消和反选。

看下Activity类的代码:

001 publicclass Ex_checkboxActivity extendsActivity {
002      
003     privateListView lv;
004     privateMyAdapter mAdapter;
005     privateArrayList list;
006     privateButton bt_selectall;
007     privateButton bt_cancel;
008     privateButton bt_deselectall;
009     privateint checkNum; // 记录选中的条目数量
010     privateTextView tv_show;// 用于显示选中的条目数量
011      
012     /** Called when the activity is first created. */
013     @Override
014     publicvoid onCreate(Bundle savedInstanceState) {
015         super.onCreate(savedInstanceState);
016         setContentView(R.layout.main);
017         /* 实例化各个控件 */
018         lv = (ListView) findViewById(R.id.lv);
019         bt_selectall = (Button) findViewById(R.id.bt_selectall);
020         bt_cancel = (Button) findViewById(R.id.bt_cancelselectall);
021         bt_deselectall = (Button) findViewById(R.id.bt_deselectall);
022         tv_show = (TextView) findViewById(R.id.tv);
023         list = newArrayList();
024         // 为Adapter准备数据
025         initDate();
026         // 实例化自定义的MyAdapter
027         mAdapter = newMyAdapter(list, this);
028         // 绑定Adapter
029         lv.setAdapter(mAdapter);
030         // 全选按钮的回调接口
031         bt_selectall.setOnClickListener(newOnClickListener() {
032             @Override
033             publicvoid onClick(View v) {
034                 // 遍历list的长度,将MyAdapter中的map值全部设为true
035                 for(inti = 0; i < list.size(); i++) {
036                     MyAdapter.getIsSelected().put(i,true);
037                 }
038                 // 数量设为list的长度
039                 checkNum = list.size();
040                 // 刷新listview和TextView的显示
041                 dataChanged();
042             }
043         });
044         // 取消按钮的回调接口
045         bt_cancel.setOnClickListener(newOnClickListener() {
046             @Override
047             publicvoid onClick(View v) {
048                 // 遍历list的长度,将已选的按钮设为未选
049                 for(inti = 0; i < list.size(); i++) {
050                     if(MyAdapter.getIsSelected().get(i)) {
051                         MyAdapter.getIsSelected().put(i,false);
052                         checkNum--;// 数量减1
053                     }
054                 }
055                 // 刷新listview和TextView的显示
056                 dataChanged();
057             }
058         });
059  
060         // 反选按钮的回调接口
061         bt_deselectall.setOnClickListener(newOnClickListener() {
062             @Override
063             publicvoid onClick(View v) {
064                 // 遍历list的长度,将已选的设为未选,未选的设为已选
065                 for(inti = 0; i < list.size(); i++) {
066                     if(MyAdapter.getIsSelected().get(i)) {
067                         MyAdapter.getIsSelected().put(i,false);
068                         checkNum--;
069                     }else{
070                         MyAdapter.getIsSelected().put(i,true);
071                         checkNum++;
072                     }
073                 }
074                 // 刷新listview和TextView的显示
075                 dataChanged();
076             }
077         });
078          
079         // 绑定listView的监听器
080         lv.setOnItemClickListener(newOnItemClickListener() {
081  
082             @Override
083             publicvoid onItemClick(AdapterView arg0, View arg1, intarg2,
084                     longarg3) {
085                 // 取得ViewHolder对象,这样就省去了通过层层的findViewById去实例化我们需要的cb实例的步骤
086 ViewHolder holder = (ViewHolder) arg1.getTag();
087                 // 改变CheckBox的状态
088                 holder.cb.toggle();
089                 // 将CheckBox的选中状况记录下来
090                 MyAdapter.getIsSelected().put(arg2, holder.cb.isChecked());
091                 // 调整选定条目
092                 if(holder.cb.isChecked() == true) {
093                     checkNum++;
094                 }else{
095                     checkNum--;
096                 }
097                 // 用TextView显示
098                 tv_show.setText("已选中"+checkNum+"项");
099             }
100         });
101     }
102     // 初始化数据
103     privatevoid initDate() {
104         for(inti = 0; i < 15; i++) {
105             list.add("data"+ "   " + i);
106         }
107     }
108     // 刷新listview和TextView的显示
109     privatevoid dataChanged() {
110         // 通知listView刷新
111         mAdapter.notifyDataSetChanged();
112         // TextView显示最新的选中数目
113         tv_show.setText("已选中"+ checkNum + "项");
114     }
115 }


代码中在item的点击事件中,直接调用
holder.cb.toggle();
先改变CheckBox的状态,然后将值存进map记录下来
MyAdapter.getIsSelected().put(arg2, holder.cb.isChecked());
而其他几个Button的点击事件,都是通过遍历list的长度来设置isSelected的值,进而通知listview根据已经变化的adapter刷新,来实现Checkbox的对应选中状态。因为对listview的处理中我们仍然使用了ViewHolder来优化ListView的效率(通过findViewById层层查找是比较耗时的,全面解析listview的),来看下运行效果:
1.JPG 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值