我有一个回收器视图适配器,就像我提供的代码一样。在列表足够大到可以滚动之前,使用操作栏删除功能可以很好地工作。
当列表很大时,选择多个项目并点击delete并不会删除确切的选定项目。它删除了一些其他的项目。但就像总是在删除后,当列表不再需要滚动时,它会删除确切的选定项目。
那么我到底做错了什么呢?
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");
}
}
}
}发布于 2019-07-25 15:01:23
for (int pos : sel_pos_lis) {
arr_lis_his_dat.remove(pos);
}你代码的这一部分有一个问题,当你在某个位置删除一些项目时,下一个项目的位置将会改变,其他删除操作可能会失败,并删除其他一些项目。你应该先删除索引较高的选项,但这与滚动和大列表无关。
发布于 2019-07-25 13:29:37
在你的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());
}
}
});https://stackoverflow.com/questions/57194830
复制相似问题