国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

RecyclerView中使用CheckBox出現勾選混亂的解決方法

2019-10-22 18:18:01
字體:
來源:轉載
供稿:網友

熟悉RecyclerView的人應該都知道,RecyclerView使用了復用機制,當在RecyclerView中得每一項都添加一個CheckBox時,勾選當前頁面的幾個CheckBox會發現下面還有其他的CheckBox也被勾選了,今天我們就來討論一下如何解決這個問題。

首先當然是創建一個項目,然后在activity_main中添加一個RecyclerView控件,當然,在這之前,我們需要先添加RecyclerView的依賴,如下圖:

RecyclerView,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">      <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, 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,代碼如下:

<?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, 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:

<?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, 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

此項目已上傳到githut:點擊打開鏈接

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 牟定县| 宁城县| 乌鲁木齐县| 石狮市| 陵水| 黑山县| 黔西| 晋州市| 阳原县| 榆社县| 平凉市| 永泰县| 通城县| 道真| 桑日县| 阿拉尔市| 苏尼特左旗| 广汉市| 阜阳市| 宜都市| 鹰潭市| 天祝| 隆昌县| 江津市| 佳木斯市| 乌拉特前旗| 垦利县| 喀什市| 肥城市| 康乐县| 荣昌县| 连州市| 达孜县| 甘泉县| 南部县| 周口市| 北宁市| 宁都县| 汝州市| 凌云县| 页游|