andoid-解决RecyclerView+CheckBox选中混乱的问题

引子

今天,使用RecyclerView + Checkbox的时候,发生了checkbox状态错乱的问题。

RecyclerView 为了提高效率,使用了Recycler回收机制,它的作用就是,不会产生多余的itemView,如果产生了向上滑动,就将最上方的itemView保存起来,然后接到最下面,然后重新加载数据(onBindViewHolder会被调用)。

但是这种方式,如果itemView中有checkbox,要继承之前的勾选状态,那就坑了爹了。因为重用的itemView会保留之前的check状态。

必须要想办法,标记它的勾选状态,才能正常显示勾选。

 

代码

解决此问题,最重要的代码在adapter里面。红色的,是关键代码.

主要思路: 利用一组map来记录每一个checkbox的选中状态,然后在checkbox的选中事件中,对这个map进行维护。具体的,请看下面代码。

 

 1 import android.content.Context;
 2 import android.support.annotation.NonNull;
 3 import android.support.v7.widget.RecyclerView;
 4 import android.view.LayoutInflater;
 5 import android.view.View;
 6 import android.view.ViewGroup;
 7 import android.widget.CheckBox;
 8 import android.widget.CompoundButton;
 9 import android.widget.TextView;
10 
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 
16 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
17 
18     private Context context;
19 
20     //先造一组模拟数据
21     private List<String> listData;
22 
23     private Map<Integer, Boolean> checkStatus;//用来记录所有checkbox的状态
24 
25     public MyAdapter(Context context) {
26         this.context = context;
27         initData();
28     }
29 
30     private void initData() {
31         listData = new ArrayList<>();
32         for (int i = 0; i < 100; i++) {
33             listData.add("testData" + i);
34         }
35 
36         checkStatus = new HashMap<>();
37         for (int i = 0; i < listData.size(); i++) {
38             checkStatus.put(i, false);// 默认所有的checkbox都是没选中
39         }
40 
41     }
42 
43     public class MyViewHolder extends RecyclerView.ViewHolder {
44         CheckBox checkbox;
45         TextView textView;
46 
47         public MyViewHolder(View itemView) {
48             super(itemView);
49             checkbox = itemView.findViewById(R.id.checkbox);
50             textView = itemView.findViewById(R.id.textView);
51         }
52     }
53 
54     @NonNull
55     @Override
56     public MyAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
57         View v = LayoutInflater.from(context).inflate(R.layout.layout, parent, false);
58         MyViewHolder holder = new MyViewHolder(v);
59         return holder;
60     }
61 
62     @Override
63     public void onBindViewHolder(@NonNull MyAdapter.MyViewHolder holder, final int position) {
64         holder.textView.setText(listData.get(position));
65         holder.checkbox.setOnCheckedChangeListener(null);//清掉监听器
66         holder.checkbox.setChecked(checkStatus.get(position));//设置选中状态
67         holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {//再设置监听器
68             @Override
69             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
70                 checkStatus.put(position, isChecked);//check状态一旦改变,保存的check值也要发生相应的变化
71             }
72         });
73     }
74 
75     @Override
76     public int getItemCount() {
77         if (listData == null) return 0;
78         return listData.size();
79     }
80 }

 

下面给出其他代码:

MainActivity.java

 1 package com.example.recyclerview2;
 2 
 3 import android.support.v7.app.AppCompatActivity;
 4 import android.os.Bundle;
 5 import android.support.v7.widget.LinearLayoutManager;
 6 import android.support.v7.widget.RecyclerView;
 7 
 8 public class MainActivity extends AppCompatActivity {
 9 
10     private RecyclerView rv_1;
11 
12     @Override
13     protected void onCreate(Bundle savedInstanceState) {
14         super.onCreate(savedInstanceState);
15         setContentView(R.layout.activity_main);
16 
17         rv_1 = findViewById(R.id.rv_1);
18         RecyclerView.LayoutManager manager = new LinearLayoutManager(this);
19         rv_1.setLayoutManager(manager);
20         MyAdapter adapter = new MyAdapter(this);
21         rv_1.setAdapter(adapter);
22     }
23 
24 
25 }

 

activity_main.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     tools:context=".MainActivity">
 7 
 8     <android.support.v7.widget.RecyclerView
 9         android:id="@+id/rv_1"
10         android:layout_width="match_parent"
11         android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
12 
13 </android.support.constraint.ConstraintLayout>

layout.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="wrap_content"
 5     android:gravity="center"
 6     android:orientation="horizontal">
 7 
 8     <TextView
 9         android:id="@+id/textView"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content"
12         android:layout_margin="10dp"
13         android:text="111" />
14 
15     <CheckBox
16         android:id="@+id/checkbox"
17         android:layout_width="wrap_content"
18         android:layout_height="wrap_content"
19         android:layout_margin="10dp" />
20 
21 </LinearLayout>

 

结语:

 这里有一句代码很精髓,那就是

holder.checkbox.setOnCheckedChangeListener(null);//清掉监听器

Checkbox的监听器有一个特性,无论你是认为操作,还是用api来setChecked,都会触发监听器。所以,在itemView重新加载好之前,不要设置checkbox的check事件监听,否则会出现另外的混乱情况,有兴趣的可以试试看。

问题已解决,OK,就酱紫。

 

转载于:https://www.cnblogs.com/hankzhouAndroid/p/9139757.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值