RecyclerView中使用CheckBox出现勾选混乱的解决方法

RecyclerView中使用CheckBox出现勾选混乱的解决方法,第1张

概述熟悉RecyclerView的人应该都知道,RecyclerView使用了复用机制,当在RecyclerView中得每一项都添加一个CheckBox时,勾选当前页面的几个CheckBox会发现下面还有其他的CheckBox也被勾选了,今天我们就来讨论一下如何解

熟悉RecyclerVIEw的人应该都知道,RecyclerVIEw使用了复用机制,当在RecyclerVIEw中得每一项都添加一个CheckBox时,勾选当前页面的几个CheckBox会发现下面还有其他的CheckBox也被勾选了,今天我们就来讨论一下如何解决这个问题。

首先当然是创建一个项目,然后在activity_main中添加一个RecyclerVIEw控件,当然,在这之前,我们需要先添加RecyclerVIEw的依赖,如下图:

然后 开始编辑activity_main:

<?xml version="1.0" enCoding="utf-8"?> <linearLayout    xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:layout_wIDth="match_parent"   androID:layout_height="match_parent"   androID:orIEntation="vertical">      <androID.support.v7.Widget.RecyclerVIEw     androID:ID="@+ID/ID_recycler_vIEw"     androID:layout_wIDth="match_parent"     androID:layout_height="match_parent">        </androID.support.v7.Widget.RecyclerVIEw> </linearLayout> 

接下来为这个RecyclerVIEw创建一个item布局文件,命名为item_recyclervIEw,并添加一个CheckBox空间,代码如下:

<?xml version="1.0" enCoding="utf-8"?> <linearLayout    xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:orIEntation="vertical"    androID:layout_wIDth="match_parent"   androID:layout_height="60dp"   androID:gravity="center_vertical">    <CheckBox     androID:ID="@+ID/ID_check_Box"     androID:layout_wIDth="match_parent"     androID:layout_height="wrap_content"     androID:layout_marginleft="10dp"     androID:text="CheckBox"/> </linearLayout> 

接下来要编辑MainActivity了,包括从布局文件中找到刚才的RecyclerVIEw控件,然后为其设置Adapter等,过程不再详细叙述,编辑后的代码如下:

public class MainActivity extends AppCompatActivity {    private RecyclerVIEw recyclerVIEw;   private MyAdapter myAdapter;    @OverrIDe   protected voID onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentVIEw(R.layout.activity_main);      recyclerVIEw = (RecyclerVIEw) findVIEwByID(R.ID.ID_recycler_vIEw);     myAdapter = new MyAdapter();     recyclerVIEw.setLayoutManager(new linearlayoutmanager(this));     recyclerVIEw.setAdapter(myAdapter);   }      private class MyAdapter extends RecyclerVIEw.Adapter {      private List<String> content;      @OverrIDe     public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,int vIEwType) {       VIEw vIEw = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_recyclervIEw,parent,false);       return new MyVIEwHolder(vIEw);     }      @OverrIDe     public voID onBindVIEwHolder(RecyclerVIEw.VIEwHolder holder,int position) {       MyVIEwHolder myVIEwHolder = (MyVIEwHolder) holder;       myVIEwHolder.checkBox.setText(content.get(position));      }      @OverrIDe     public int getItemCount() {       content = new ArrayList<>();       for (int i = 0; i < 100; i++) {         content.add("CheckBox" + i);       }       return content.size();     }   }     private class MyVIEwHolder extends RecyclerVIEw.VIEwHolder {      private CheckBox checkBox;      public MyVIEwHolder(VIEw itemVIEw) {       super(itemVIEw);       checkBox = (CheckBox) itemVIEw.findVIEwByID(R.ID.ID_check_Box);     }   } } 

可以看到,我们为这个RecyclerVIEw设置了100个item,每个item里面都含有一个CheckBox,这时候运行这个应用,勾选出现的屏幕上的某一个或者多个CheckBox之后,当你向下拉的时候,问题出现了,你会发现下面会有很多的CheckBox也被选中了。下面我们就来着手解决这个问题,其实要解决也很简单,可以定义一个boolean类型的数组或者列表,用它来控制CheckBox的选中状态,当某个CheckBox被选中的时候将其选中状态记录在数组或列表中,当某个CheckBox滚动到屏幕上的时候,再用数组或列表中对应的值把它的选中状态改回来就好了,修改后的代码如下:

public class MainActivity extends AppCompatActivity {    private RecyclerVIEw recyclerVIEw;   private MyAdapter myAdapter;    @OverrIDe   protected voID onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentVIEw(R.layout.activity_main);      recyclerVIEw = (RecyclerVIEw) findVIEwByID(R.ID.ID_recycler_vIEw);     myAdapter = new MyAdapter();     recyclerVIEw.setLayoutManager(new linearlayoutmanager(this));     recyclerVIEw.setAdapter(myAdapter);   }      private class MyAdapter extends RecyclerVIEw.Adapter {      private List<String> content;     private boolean[] flag = new boolean[100];//此处添加一个boolean类型的数组      @OverrIDe     public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,final int position) {       MyVIEwHolder myVIEwHolder = (MyVIEwHolder) holder;       myVIEwHolder.checkBox.setText(content.get(position));              myVIEwHolder.checkBox.setonCheckedchangelistener(null);//先设置一次CheckBox的选中监听器,传入参数null       myVIEwHolder.checkBox.setChecked(flag[position]);//用数组中的值设置CheckBox的选中状态              //再设置一次CheckBox的选中监听器,当CheckBox的选中状态发生改变时,把改变后的状态储存在数组中       myVIEwHolder.checkBox.setonCheckedchangelistener(new Compoundbutton.OnCheckedchangelistener() {         @OverrIDe         public voID onCheckedChanged(Compoundbutton compoundbutton,boolean b) {           flag[position] = b;         }       });     }      @OverrIDe     public int getItemCount() {       content = new ArrayList<>();       for (int i = 0; i < 100; i++) {         content.add("CheckBox" + i);       }       return content.size();     }   }     private class MyVIEwHolder extends RecyclerVIEw.VIEwHolder {      private CheckBox checkBox;      public MyVIEwHolder(VIEw itemVIEw) {       super(itemVIEw);       checkBox = (CheckBox) itemVIEw.findVIEwByID(R.ID.ID_check_Box);     }   } } 

比较这两段代码,我们会发现,首先我们定义了一个长度为100的数组,然后设置CheckBox的选中监听器,把null作为参数传进去,然后用数组中的值设置对应CheckBox的选中状态,最后再一次设置CheckBox的选中监听器,把CheckBox的选中状态储存在数组中的相应位置中。再次运行,发现问题已解决。

下面我们来讨论一下,如果要在RecyclerVIEw的外面再添加一个CheckBox,用外面的CheckBox来控制RecyclerVIEw中的CheckBox的全选和取消全选,要如何实现呢?

其实也很简单,只要用这个CheckBox来控制之前所定义的数组的指就好了。

首先来修改一下activity_main,代码如下:

<?xml version="1.0" enCoding="utf-8"?> <linearLayout   xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:layout_wIDth="match_parent"   androID:layout_height="match_parent"   androID:orIEntation="vertical">      <linearLayout     androID:layout_wIDth="match_parent"     androID:layout_height="60dp"     androID:gravity="center_vertical">     <CheckBox       androID:ID="@+ID/ID_select_all"       androID:layout_wIDth="match_parent"       androID:layout_height="wrap_content"       androID:layout_marginleft="10dp"       androID:text="SelectAll"/>   </linearLayout>    <androID.support.v7.Widget.RecyclerVIEw     androID:ID="@+ID/ID_recycler_vIEw"     androID:layout_wIDth="match_parent"     androID:layout_height="match_parent">    </androID.support.v7.Widget.RecyclerVIEw> </linearLayout> 

我们在RecyclerVIEw的外面添加了一个CheckBox,用这个CheckBox来控制RecyclerVIEw中的CheckBox的全选,接下来修改MainActivity:

public class MainActivity extends AppCompatActivity {    private CheckBox selectAll;   private RecyclerVIEw recyclerVIEw;   private MyAdapter myAdapter;   private boolean []flag;//把flag数组定义为全局变量    @OverrIDe   protected voID onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentVIEw(R.layout.activity_main);      selectAll = (CheckBox) findVIEwByID(R.ID.ID_select_all);     recyclerVIEw = (RecyclerVIEw) findVIEwByID(R.ID.ID_recycler_vIEw);     flag = new boolean[100];//初始化flag     myAdapter = new MyAdapter();     recyclerVIEw.setLayoutManager(new linearlayoutmanager(this));     recyclerVIEw.setAdapter(myAdapter);      //设置外面CheckBox的选中监听器,把它的选中状态赋值给其他的所有CheckBox,然后更新RecyclerVIEw的Adapter     selectAll.setonCheckedchangelistener(new Compoundbutton.OnCheckedchangelistener() {       @OverrIDe       public voID onCheckedChanged(Compoundbutton compoundbutton,boolean b) {         for (int i = 0; i < 100; i++) {           flag[i] = b;         }         myAdapter.notifyDataSetChanged();       }     });   }      private class MyAdapter extends RecyclerVIEw.Adapter {      private List<String> content; //    private boolean[] flag = new boolean[100];      @OverrIDe     public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,final int position) {       MyVIEwHolder myVIEwHolder = (MyVIEwHolder) holder;       myVIEwHolder.checkBox.setText(content.get(position));       myVIEwHolder.checkBox.setonCheckedchangelistener(null);       myVIEwHolder.checkBox.setChecked(flag[position]);       myVIEwHolder.checkBox.setonCheckedchangelistener(new Compoundbutton.OnCheckedchangelistener() {         @OverrIDe         public voID onCheckedChanged(Compoundbutton compoundbutton,boolean b) {           flag[position] = b;         }       });       }      @OverrIDe     public int getItemCount() {       content = new ArrayList<>();       for (int i = 0; i < 100; i++) {         content.add("CheckBox" + i);       }       return content.size();     }   }     private class MyVIEwHolder extends RecyclerVIEw.VIEwHolder {      private CheckBox checkBox;      public MyVIEwHolder(VIEw itemVIEw) {       super(itemVIEw);       checkBox = (CheckBox) itemVIEw.findVIEwByID(R.ID.ID_check_Box);     }   } } 

这里我们先把记录CheckBox选中状态的数组定义为全局变量,然后设置外面的CheckBox的监听器,把它的选中状态赋值给其他的所有CheckBox,紧接着更新一下RecyclerVIEw的Adapter就可以了

这里我们在讨论一下RecyclerVIEw的另外一个问题,就是当要删除某个子项的时候会出现删除紊乱的情况,为了说明这个问题,我们

先来尝试实践一下,修改item_recyclervIEw:

<?xml version="1.0" enCoding="utf-8"?> <relativeLayout   xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:layout_wIDth="match_parent"   androID:layout_height="60dp"   androID:gravity="center_vertical">    <CheckBox     androID:ID="@+ID/ID_check_Box"     androID:layout_wIDth="match_parent"     androID:layout_height="wrap_content"     androID:layout_marginleft="10dp"     androID:text="CheckBox"/>      <button     androID:layout_wIDth="wrap_content"     androID:layout_height="wrap_content"     androID:layout_alignParentRight="true"     androID:layout_marginRight="10dp"     androID:text="delete"/> </relativeLayout> 

我们增加了一个button,接下来设置这个button,当它被点击的时候就删除它所在位置的item,修改MainActivity如下,主要修改的是Adapter部分,其他部分的代码就不贴了:

private class MyAdapter extends RecyclerVIEw.Adapter {  //    private List<String> content; //    private boolean[] flag = new boolean[100];      @OverrIDe     public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,final int position) {       final MyVIEwHolder myVIEwHolder = (MyVIEwHolder) holder;       myVIEwHolder.checkBox.setText(content.get(position));       myVIEwHolder.checkBox.setonCheckedchangelistener(null);       myVIEwHolder.checkBox.setChecked(flag[position]);       myVIEwHolder.checkBox.setonCheckedchangelistener(new Compoundbutton.OnCheckedchangelistener() {         @OverrIDe         public voID onCheckedChanged(Compoundbutton compoundbutton,boolean b) {           flag[position] = b;         }       });       //设置监听器,当按钮被点击是,删除它所在的item       myVIEwHolder.button.setonClickListener(new VIEw.OnClickListener() {         @OverrIDe         public voID onClick(VIEw vIEw) {           content.remove(position);           notifyItemRemoved(position);         }       });       }      @OverrIDe     public int getItemCount() { //      content = new ArrayList<>(); //      for (int i = 0; i < 100; i++) { //        content.add("CheckBox" + i); //      }       return content.size();     }   }     private class MyVIEwHolder extends RecyclerVIEw.VIEwHolder {      private CheckBox checkBox;     private button button;//定义删除按钮      public MyVIEwHolder(VIEw itemVIEw) {       super(itemVIEw);       checkBox = (CheckBox) itemVIEw.findVIEwByID(R.ID.ID_check_Box);       button = (button) itemVIEw.findVIEwByID(R.ID.ID_delete);     }   } 

这是点击button,我们会发现,问题出现了,第一次可以正常删除,第二次删除的item却是我们点击的button所在的下一个item,后面的删除也会各种混乱,这是因为函数里面的传入的参数position,它是在进行onBind *** 作时确定的,在删除单项后,已经出现在画面里的项不会再有调用onBind机会,这样它保留的position一直是未进行删除 *** 作前的postion值,对于尚未进入画面的单项来说,它会使用新的position值(好吧这段是抄的,其实我也不太懂啥意思),解决方法如下:

myVIEwHolder.button.setonClickListener(new VIEw.OnClickListener() {   @OverrIDe   public voID onClick(VIEw vIEw) {     content.remove(position);     notifyItemRemoved(position);     notifyItemRangeChanged(position,content.size());//对于被删掉的位置及其后range大小范围内的vIEw进行重新onBindVIEwHolder   } }); 

只要加一行代码就好了,这行代码的作用就是对于被删掉的位置及其后range大小范围内的vIEw进行重新onBindVIEwHolder

此项目已上传到githut:点击打开链接

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的RecyclerView中使用CheckBox出现勾选混乱的解决方法全部内容,希望文章能够帮你解决RecyclerView中使用CheckBox出现勾选混乱的解决方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143186.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存