[英]Recycler View adapter not working properly when the list is big enough to scroll
我有一個回收者視圖適配器,就像我提供的代碼一樣。 使用動作欄刪除功能,一切正常,直到列表足夠滾動為止。
如果列表很大,則選擇多個項目,然后點按“刪除”不會刪除確切的所選項目。 它刪除了其他一些項目。 但是,就像在刪除列表之后始終執行刪除操作一樣,不再需要滾動,它不再刪除確切選擇的項目。
那我在做什么錯呢?
package com.itsred1.a1wallet;
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class RVDirLisAda extends RecyclerView.Adapter<RVDirLisAda.MyViewHolder> {
private final Context m_con;
private final LayoutInflater lay_inf;
private final ArrayList<RVDat> arr_lis_his_dat;
private ArrayList<Integer> sel_pos_lis = new ArrayList<>();
private boolean mul_sel;
RVDirLisAda(Context context, ArrayList<RVDat> his_dat_arr_lis) {
m_con = context;
lay_inf = LayoutInflater.from(context);
this.arr_lis_his_dat = his_dat_arr_lis;
}
private ActionMode.Callback act_mod_cal_bac = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mul_sel = true;
menu.add("Delete");
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
for (int pos : sel_pos_lis) {
arr_lis_his_dat.remove(pos);
}
mode.finish();
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mul_sel = false;
sel_pos_lis.clear();
notifyDataSetChanged();
}
};
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View vie = lay_inf.inflate(R.layout.rv_dir_lis, parent, false);
return new MyViewHolder(vie);
}
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
holder.ini_row(position);
}
@Override
public int getItemCount() {
return arr_lis_his_dat.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private final TextView tv_fil_nam;
MyViewHolder(View itemView) {
super(itemView);
tv_fil_nam = itemView.findViewById(R.id.tv_fil_nam);
}
void ini_row(final int pos){
if (sel_pos_lis.contains(pos)){
tv_fil_nam.setBackgroundColor(Color.LTGRAY);
} else {
tv_fil_nam.setBackgroundColor(Color.WHITE);
}
final String fil_nam = arr_lis_his_dat.get(pos).get_row1_col2();
final String tra_typ = arr_lis_his_dat.get(pos).get_tra_typ();
final String id = arr_lis_his_dat.get(pos).get_row2_col1();
tv_fil_nam.setText(fil_nam);
if(tra_typ.equals("folder")) {
tv_fil_nam.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ico_fol, 0, 0, 0);
} else if (tra_typ.equals("file")) {
tv_fil_nam.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ico_db,0,0,0);
}
tv_fil_nam.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if(!mul_sel){
((AppCompatActivity) v.getContext()).startSupportActionMode(act_mod_cal_bac);
}
sel_row(pos);
return true;
}
});
tv_fil_nam.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mul_sel){
sel_row(pos);
} else {
cal_bac(id, fil_nam, pos);
}
}
});
}
void sel_row(int pos) {
if (mul_sel) {
if (sel_pos_lis.contains(pos)) {
int i = sel_pos_lis.lastIndexOf(pos);
sel_pos_lis.remove(i);
tv_fil_nam.setBackgroundColor(Color.WHITE);
} else {
sel_pos_lis.add(pos);
tv_fil_nam.setBackgroundColor(Color.LTGRAY);
}
}
}
void cal_bac(String id, String tra_typ, int pos) {
CalBacCom cal_bac_com = null;
if (m_con instanceof CalBacCom) {
cal_bac_com = (CalBacCom) m_con;
}
if (cal_bac_com != null) {
cal_bac_com.ini_cal_bac (id, tra_typ, pos, "row_cli");
}
}
}
}
在您的OnClickListener
內部,您引用的位置值可能會隨着上下滾動而快速變化。 發生這種情況是因為您的視圖持有人被重新使用,以使可見的新項目膨脹,從而避免了新的內存分配,換句話說,適配器從“隱藏”的項目中獲取視圖持有人,然后在“可見”的項目上重復使用它們滾動時。 而是在這些偵聽器中使用getAdapterPosition
方法。 例如,不要這樣做...
tv_fil_nam.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mul_sel){
sel_row(pos);
} else {
cal_bac(id, fil_nam, pos);
}
}
});
做這個...
tv_fil_nam.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mul_sel){
sel_row(getAdapterPosition());
} else {
cal_bac(id, fil_nam, getAdapterPosition());
}
}
});
for (int pos : sel_pos_lis) {
arr_lis_his_dat.remove(pos);
}
代碼的此部分存在問題,當您在某個位置刪除某些項目時,下一個項目的位置將發生變化,其他刪除操作可能會失敗並刪除其他一些項目。 您應該先刪除索引較高的選項,但這與滾動和大列表無關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.