簡體   English   中英

當列表足夠滾動時,Recycler View適配器無法正常工作

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM