首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当列表大到可以滚动时,回收器视图适配器无法正常工作

当列表大到可以滚动时,回收器视图适配器无法正常工作
EN

Stack Overflow用户
提问于 2019-07-25 13:22:33
回答 2查看 136关注 0票数 0

我有一个回收器视图适配器,就像我提供的代码一样。在列表足够大到可以滚动之前,使用操作栏删除功能可以很好地工作。

当列表很大时,选择多个项目并点击delete并不会删除确切的选定项目。它删除了一些其他的项目。但就像总是在删除后,当列表不再需要滚动时,它会删除确切的选定项目。

那么我到底做错了什么呢?

代码语言:javascript
运行
复制
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");
            }
        }

    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-25 15:01:23

代码语言:javascript
运行
复制
for (int pos : sel_pos_lis) {
    arr_lis_his_dat.remove(pos);
}

你代码的这一部分有一个问题,当你在某个位置删除一些项目时,下一个项目的位置将会改变,其他删除操作可能会失败,并删除其他一些项目。你应该先删除索引较高的选项,但这与滚动和大列表无关。

票数 1
EN

Stack Overflow用户

发布于 2019-07-25 13:29:37

在你的OnClickListener中,你正在引用一个位置值,当你向上或向下滚动时,这个位置值可能会很快改变。之所以会发生这种情况,是因为您的视图持有者被重用来膨胀变为可见的新项,从而避免了新的内存分配,换句话说,适配器从变为“隐藏”的项中获取视图符,并在滚动时将其重用于变为“可见”的项。取而代之的是在这些侦听器中使用getAdapterPosition方法。例如,与其这样做,不如...

代码语言:javascript
运行
复制
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);
                }
            }
        });

这样做..。

代码语言:javascript
运行
复制
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());
                }
            }
        });
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57194830

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档