美文网首页
2-4-8 ListView的checkbox错位问题

2-4-8 ListView的checkbox错位问题

作者: 努力学习的安同学 | 来源:发表于2018-06-19 18:02 被阅读0次

    标注:本文为个人整理,仅做自己学习参考使用,请勿转载和转发
    2018-06-19: 初稿。参考博主coder-pig

    0. 引言

    • 这个问题主要是ListView的item中,上面带有一个checkbox的话,那么当item的数量超过1页话,就会出现这个问题

    1. 问题原因

    • 关于ListView的getView方法调用机制的一个图


      image
    • 上面的图中有一个Recycler的东西,平时我们ListView上可见的Item处于内存中,而且他的Item则存放在这个Recycler中

    • 第一次加载Item时,当前页面中的convertView都为null,当滚出屏幕,这个时候ConvertView不为空,所以新的一项会复用这个convertView!


      image
    • 从图中可以看出,Positon从12开始,ConviertView就不为空了,具体这个代表什么,我也不知道。。。只是知道这个ConvertView会缓存就好,就是因为这个原因造成checkbox错位。

    • 所以第一个解决方法就是,不重用这个ConvertView,或者说每次getView都将这个convertView都设置成null,但是如果需要显示item的树木巨大的话,这个方法就显得非常臃肿。

    • 所以一般采用的解决办法就是,找一个东西将当前的item CheckBox的状态保存起来,初始化的时候进行判断,设置是否选中。

    2. 解决办法示例

    • 好的储存这个CheckBox的方法有很多,可以存放一个HashMap<Integer, boolean>,每次初始化的时候根据position取出对应的boolean值,然后进行checkbox的状态值
    • 本文的做法是将entity类中加入了一个boolean值用于判断,下面是一个项目抽出来的代码,代码比较简单
      Entity类
    public class Person implements Serializable{
        private String name;
        private String number;
        private boolean checkStatus;
        
        public Person(String name, String number) {
            super();
            this.name = name;
            this.number = number;
            this.checkStatus = false;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getNumber() {
            return number;
        }
    
        public void setNumber(String number) {
            this.number = number;
        }
    
        public boolean getCheckStatus() {
            return checkStatus;
        }
    
        public void setCheckStatus(boolean checkStatus) {
            this.checkStatus = checkStatus;
        }
        
    }
    

    实现的Adapter类:ContactListAdapter.java:

    public class ContactListAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener{
    
        private List<Person> mData;
        private Context mContext;
    
        public ContactListAdapter(List<Person> data, Context context) {
            mData = data;
            mContext = context;
        }
    
        // 定义一个刷新数据的方法
        public void changeData(List<Person> data) {
            mData = data;
            notifyDataSetChanged();
        }
    
        @Override
        public int getCount() {
            return mData.size();
        }
    
        @Override
        public Person getItem(int position) {
            return mData.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final int index = position;
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(
                        R.layout.item_contact, parent, false);
                viewHolder = new ViewHolder();
                viewHolder.ly = (RelativeLayout) convertView
                        .findViewById(R.id.lyContactListItem);
                viewHolder.txtName = (TextView) convertView
                        .findViewById(R.id.txtName);
                viewHolder.txtNumber = (TextView) convertView
                        .findViewById(R.id.txtNumber);
                viewHolder.cbxStatus = (CheckBox) convertView
                        .findViewById(R.id.cbxStatus);
                convertView.setTag(viewHolder);
                viewHolder.cbxStatus.setTag(index);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.cbxStatus.setOnCheckedChangeListener(this);
            viewHolder.cbxStatus.setChecked(mData.get(position).getcheckStatus());
            viewHolder.txtName.setText(mData.get(index).getName());
            viewHolder.txtNumber.setText(mData.get(index).getNumber());
            return convertView;
        }
    
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            int index = (int)buttonView.getTag();
            if (isChecked)
                mData.get(index).setCheckStatus(true);
            else
                mData.get(index).setCheckStatus(false);
        }
    
    
        private class ViewHolder {
            RelativeLayout ly;
            TextView txtName;
            TextView txtNumber;
            CheckBox cbxStatus;
        }
    }
    
    • 非常简单,另外别忘了一点: checkbox监听器的方法要添加在初始化Checkbox状态的代码之前哦~

    这个方法是在item的对象的类中添加了对checkbox的set和get的方法,在Adapter中添加了对checkout的监听onCheckedChanged, 在getView中直接取出对应的item对象类中的状态,初始化的checkbox的为flase,然后通过监听设置状态。

    相关文章

      网友评论

          本文标题:2-4-8 ListView的checkbox错位问题

          本文链接:https://www.haomeiwen.com/subject/elfzeftx.html