RecyclerView中如何解决使用CheckBox出现勾选混乱的问题

这篇文章给大家分享的是有关RecyclerView中如何解决使用CheckBox出现勾选混乱的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

主要从事网页设计、PC网站建设(电脑版网站建设)、wap网站建设(手机版网站建设)、响应式网站开发、程序开发、微网站、小程序开发等,凭借多年来在互联网的打拼,我们在互联网网站建设行业积累了丰富的成都网站制作、成都做网站、网络营销经验,集策划、开发、设计、营销、管理等多方位专业化运作于一体,具备承接不同规模与类型的建设项目的能力。

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

RecyclerView中如何解决使用CheckBox出现勾选混乱的问题

然后 开始编辑activity_main:

 
 
   
   
     
   

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

 
 
 
   

接下来要编辑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 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 content; 
    private boolean[] flag = new boolean[100];//此处添加一个boolean类型的数组 
 
    @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, 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,代码如下:

 
 
   
   
     
   
 
   
 
   

我们在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 content; 
//    private boolean[] flag = new boolean[100]; 
 
    @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, 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:

 
 
 
   
   
   

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

private class MyAdapter extends RecyclerView.Adapter { 
 
//    private List content; 
//    private boolean[] flag = new boolean[100]; 
 
    @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, 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

感谢各位的阅读!关于“RecyclerView中如何解决使用CheckBox出现勾选混乱的问题”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!


网页名称:RecyclerView中如何解决使用CheckBox出现勾选混乱的问题
本文URL:http://pwwzsj.com/article/psipgi.html