ListView + CheckBox(或者是RadioGroup等控件)的混乱选中原理

1,常用的写法,只展示Adapter,问题原因就在Adapter中



    class Adapter1 extends BaseAdapter{

        @Override
        public int getCount() {
            return list.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) {
            final int index = position;
            ViewHolder viewHolder;
            if(convertView == null){
                viewHolder = new ViewHolder();
                convertView = LayoutInflater.from(ListViewCheckBox.this).inflate(R.layout.listview_checkbox_item, null);
                viewHolder.layout = (LinearLayout)convertView.findViewById(R.id.layout);
                viewHolder.textView = (TextView)convertView.findViewById(R.id.textView);
                viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.checkBox);
                convertView.setTag(viewHolder);
            }else{
                viewHolder = (ViewHolder)convertView.getTag();
            }


            viewHolder.textView.setText(list.get(position).name);
            if(list.get(position).type == A.TYPE_CHECKED){
                viewHolder.checkBox.setChecked(true);
            }else{
                viewHolder.checkBox.setChecked(false);
            }

            /*点击checkBox所在行改变checkBox状态*/
            /*final ViewHolder vv = viewHolder;
            viewHolder.layout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(vv.checkBox.isChecked()){
                        vv.checkBox.setChecked(false);
                        list.get(index).type = TYPE_CHECKED;
                    }else{
                        vv.checkBox.setChecked(true);
                        list.get(index).type = TYPE_NOCHECKED;
                    }

                }
            });*/

            viewHolder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if(isChecked){
                        list.get(index).type = A.TYPE_CHECKED;
                    }else{
                        list.get(index).type = A.TYPE_NOCHECKED;
                    }
                }
            });

            return convertView;
        }
    }

    class ViewHolder{
        LinearLayout layout;
        TextView textView;
        CheckBox checkBox;
    }

    class A {

        public static final int TYPE_CHECKED = 1;
        public static final int TYPE_NOCHECKED = 0;

        String name;
        int type;

        public A(String name,int type){
            this.name = name;
            this.type = type;
        }
    }
}

这时出现了混乱选中问题,为什么呢?

首先,我们使用了一个数组来存储每个CheckBox的状态,如果被选中,我们在setOnCheckedChangeListener 监听事件中的OnCheckChanged()方法中将状态修改为被选中,如果被取消选中,则改为被取消选中。

我们还使用了Convertview + ViewHolder来进行view的复用,提高listView的加载效率以及减少每次new一个View 的开销。这也是导致我们出现了混乱选中的根源所在。

下面来分析下到底是如何出现的混乱选中。

1,假设我们的convertview有着10个复用的View对象(这个好像会跟显示View时,一个屏幕能放下多少View相关,如果最多只能显示五个,那么只使用5个用来复用的View),那么当我们分别用完了这十个之后就会开始复用,比如说我的界面中有30个用ListView+CheckBox组成的选择题。

我们从其他地方点进ListView所在的Activity,ListView进行加载,那么前10个是没有问题的。假设第一个我们进行了选择,状态为Checked。当我们下滑,显示到第11个的时候,这个时候第11个viewItem会复用第一个item的View。

这时。当将这一个viewItem加载到ListView的第11个位置时,它的状态是Checked。通过从状态数组中读取第11个Item的选中状态时,发现我并没有选中第11个Item,这时就会将第11个Item设置为未选中。

一切看起来这么顺利!!!

但是!

当我们的第11个Item从复用的第一个ItemView的选中状态 到 从状态数组中读取的未选中状态,是经过了一次setOnCheckedChangeListener 选中变化事件的监听的。

而且!!

我们仔细看,我们的setOnCheckedChangeListener 监听事件的设置是写在了我们初始化item的选中状态之后的。

也就是说!!

这时候我们的setOnCheckedChangeListener 监听事件是在第一个ViewItem初始化时设置的那个监听事件。

这个时候,由于发生了选中状态的变化,由第一个Item的选中变化监听事件所监听到了,从而改变了第一个Item的状态。当滑动几次时,由于反复的在复用convertView,便出现了非常令人头疼的混乱选中。。!

解决办法:把添加监听器的方法加到初始化view中checkBox状态的代码之前即可
。这时监听器便不会混乱监听了。

完美~~~

class Adapter1 extends BaseAdapter{

        @Override
        public int getCount() {
            return list.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) {
            final int index = position;
            ViewHolder viewHolder;
            if(convertView == null){
                viewHolder = new ViewHolder();
                convertView = LayoutInflater.from(ListViewCheckBox.this).inflate(R.layout.listview_checkbox_item, null);
                viewHolder.layout = (LinearLayout)convertView.findViewById(R.id.layout);
                viewHolder.textView = (TextView)convertView.findViewById(R.id.textView);
                viewHolder.checkBox = (CheckBox)convertView.findViewById(R.id.checkBox);
                convertView.setTag(viewHolder);
            }else{
                viewHolder = (ViewHolder)convertView.getTag();
            }

            viewHolder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if(isChecked){
                        list.get(index).type = A.TYPE_CHECKED;
                    }else{
                        list.get(index).type = A.TYPE_NOCHECKED;
                    }
                }
            });

            viewHolder.textView.setText(list.get(position).name);
            if(list.get(position).type == A.TYPE_CHECKED){
                viewHolder.checkBox.setChecked(true);
            }else{
                viewHolder.checkBox.setChecked(false);
            }
            return convertView;
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值