ListView中Checkbox选择混乱的三种解决方式

ListView中Checkbox选择混乱的三种解决方式

问题描述

ListView中checkbox点击混乱的问题,可采用如下三种较好的方式解决。

先看错误代码

public class MainActivity extends AppCompatActivity {

    private WebView wv;
    private Button btn;
    private ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lv = (ListView) findViewById(R.id.lv);
        lv.setAdapter(new MyAdapter());


    }

    private class MyAdapter extends BaseAdapter {

        private List<CheckBean>  beans = new ArrayList<>();

        public MyAdapter(){
            for (int i = 0; i < 50; i++) {
                CheckBean bean = new CheckBean();
                bean.setName("check : " + i);
                bean.setChecked(false);
                beans.add(bean);
            }
        }

        @Override
        public int getCount() {
            return 50;
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public View getView(final int i, View contentView, ViewGroup viewGroup) {
            final int index = i;


            ViewHolder holder = null;
            if(contentView == null) {
                contentView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.lv_item,viewGroup,false);
                holder = new ViewHolder(contentView);
            } else {
                holder = (ViewHolder) contentView.getTag();
            }

            holder.checkBox.setChecked(beans.get(i).isChecked());
            holder.tv.setText("position:" + i);


            holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    beans.get(i).setChecked(b);
                }
            });
            return contentView;
        }

    }

    private static class ViewHolder {
        private TextView tv;
        private CheckBox checkBox;
        private View contentView;

        public ViewHolder(View view) {
            this.contentView = view;
            tv = contentView.findViewById(R.id.tv);
            checkBox = contentView.findViewById(R.id.cb);
            contentView.setTag(this);
        }
    }
}

此代码思路是在JavaBean中定义一个isCheck的属性,滑动时根据此属性来判断选择状态,这样会造成一个问题:
当勾选第0个条目时,此时isCheck状态为true,滑动条目到新的条目会复用第一个条目,而此时OnCheckedChangeListener还未绑定新的条目,依然会调用第0个条目的回调,因此,当往回滑动时,第0个条目的isCheck状态依然会变成false

第一种解决办法

将setOnCheckedChangeListener写在setCheck方法上面,这样每次item绑定的都是最新的条目:

 holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     @Override
     public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
         beans.get(i).setChecked(b);
     }
 });
 holder.checkBox.setChecked(beans.get(i).isChecked());

第二种解决办法

不用setOnCheckedChangeListener,改用setOnClickListener

holder.checkBox.setOnClickListener(new View.OnClickListener() {
         @Override
          public void onClick(View view) {
              beans.get(i).setChecked(!beans.get(i).isChecked());
              finalHolder.checkBox.setChecked(beans.get(i).isChecked());
          }
 });

第三种解决办法

这种解决办法类似于第二种,只是ListView内部已经早就帮我们考虑到了这种问题的出现,并给出了解决办法。
ListView内部为我们提供的一个保存选中状态的数据结构:

SparseBooleanArray mCheckStates;

还有相应的API:

getCheckedItemCount()
getCheckedItemPositions()
setItemChecked(int postion,boolean b)

1.在ListView初始化时选择模式:

  lv = (ListView) findViewById(R.id.lv);
  lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
  lv.setAdapter(new MyAdapter());

2、在getView方法中,这样写:

@Override
       public View getView(final int postion, View convertView, ViewGroup viewGroup) {
           if (convertView == null) {
               convertView = View.inflate(MainActivity.this, R.layout.item, null);
           }
           final AppCompatCheckBox checkBox = (AppCompatCheckBox) convertView.findViewById(R.id.checkbox);
           checkBox.setChecked(lv.isItemChecked(postion));
           checkBox.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                   lv.setItemChecked(postion,checkBox.isChecked());
               }
           });
           return convertView;
       }

猜你喜欢

转载自blog.csdn.net/vicwudi/article/details/80979120