在回收站视图中滚动时,它向选定的复选框列表添加了一些其他值

Posted

技术标签:

【中文标题】在回收站视图中滚动时,它向选定的复选框列表添加了一些其他值【英文标题】:while scrolling in recycler view it added some other values to the selected list of checkboxes 【发布时间】:2020-11-06 05:22:20 【问题描述】:

在这里你可以看到我有一个 plist,当用户点击 select all 按钮时,我在其中获取选定的复选框。

这是当我显示数据列表时。只有那些复选框的数据在屏幕上可见,当我向下滚动时,剩余的复选框被选中,当我再滚动一段时间时,它会重复选中复选框的另一个值

Adapter.java

public class AttendanceRegisterAdapter extends RecyclerView.Adapter<AttendanceRegisterAdapter.AttendanceViewHolder> 

    Context context;
    private ArrayList<Student> student;
    private boolean isSelectedAll;
    private ArrayList<String> plist = new ArrayList<>();

    public AttendanceRegisterAdapter(Context context, ArrayList<Student> student) 
        this.context = context;
        this.student = student;
    

    @NonNull
    @Override
    public AttendanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 

        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.template_card_student, parent, false);

        return new AttendanceViewHolder(view);
    

    public void selectAll() 
        isSelectedAll = true;
        notifyDataSetChanged();
    

    public void unSelectAll() 
        isSelectedAll = false;
        notifyDataSetChanged();
    

    @Override
    public void onBindViewHolder(@NonNull AttendanceViewHolder holder, int position) 

        final Student selectedList = student.get(position);

        holder.cbAttendance.setSelected(selectedList.getSelected());
        holder.cbAttendance.setTag(position);

        if (isSelectedAll) 
            selectedList.setSelected(true);
            plist.add(student.get(position).getStudentID());
         else 
            selectedList.setSelected(false);
            plist.remove(student.get(position).getStudentID());
        

        holder.cbAttendance.setChecked(selectedList.getSelected());


    

    @Override
    public int getItemCount() 
        return student.size();
    



    class AttendanceViewHolder extends RecyclerView.ViewHolder 

        CardView cvStudentCard;
        ImageView imgStudentPicture;
        TextView txtStudentName;
        CheckBox cbAttendance;


        public AttendanceViewHolder(@NonNull View itemView) 
            super(itemView);
            cvStudentCard = itemView.findViewById(R.id.card_student_view);
            imgStudentPicture = itemView.findViewById(R.id.img_student_picture);
            txtStudentName = itemView.findViewById(R.id.tv_card_title);
            cbAttendance = itemView.findViewById(R.id.cb_attendance);


        
    
    


【问题讨论】:

您好,欢迎来到 SO。这里的实际问题是什么? 【参考方案1】:

您在 BindViewHolder 中添加 StudentId 而不检查 plist 每次调用 BindViewHolder 时可能会添加重复值。

public class AttendanceRegisterAdapter extends RecyclerView.Adapter<AttendanceRegisterAdapter.AttendanceViewHolder> 

    Context context;
    private ArrayList<Student> student;
    private boolean isSelectedAll;
    private ArrayList<String> plist = new ArrayList<>();

    public AttendanceRegisterAdapter(Context context, ArrayList<Student> student) 
        this.context = context;
        this.student = student;
    

    @NonNull
    @Override
    public AttendanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 

        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.template_card_student, parent, false);

        return new AttendanceViewHolder(view);
    

    public void selectAll() 
        isSelectedAll = true;
        notifyDataSetChanged();
    

    public void unSelectAll() 
        isSelectedAll = false;
        
        notifyDataSetChanged();
    
   
    public Boolean checkElementExist(String element) 
        return plist.contains(element);
    
    
    public void selectLeftOver(int nextPosition) 
        for (int i = nextPosition; nextPosition > getItemCount(); i++) 
            if (!checkElementExist(student.get(i).getStudentID())) 
                plist.add(student.get(i).getStudentID());
                
        
    

    @Override
    public void onBindViewHolder(@NonNull AttendanceViewHolder holder, int position) 

        final Student selectedList = student.get(position);

        holder.cbAttendance.setSelected(selectedList.getSelected());
        holder.cbAttendance.setTag(position);

        if (isSelectedAll) 
            selectedList.setSelected(true);
            if (!checkElementExist(student.get(position).getStudentID())) 
                plist.add(student.get(position).getStudentID());
                selectLeftOver(position + 1);
                
            
         else 
            selectedList.setSelected(false);
            if (!checkElementExist(student.get(position).getStudentID())) 
                plist.remove(student.get(position).getStudentID());
                
            
        

        holder.cbAttendance.setChecked(selectedList.getSelected());


    

    @Override
    public int getItemCount() 
        return student.size();
    



    class AttendanceViewHolder extends RecyclerView.ViewHolder 

        CardView cvStudentCard;
        ImageView imgStudentPicture;
        TextView txtStudentName;
        CheckBox cbAttendance;


        public AttendanceViewHolder(@NonNull View itemView) 
            super(itemView);
            cvStudentCard = itemView.findViewById(R.id.card_student_view);
            imgStudentPicture = itemView.findViewById(R.id.img_student_picture);
            txtStudentName = itemView.findViewById(R.id.tv_card_title);
            cbAttendance = itemView.findViewById(R.id.cb_attendance);


        
    
    


【讨论】:

感谢此解决方案有效,但另一个问题是它仅添加了屏幕上可见的复选框的值。就像我有 20 个复选框和 2 个按钮。一个用于显示已选,一个用于全选。如果用户按下全选按钮,那么它只会添加 15 个复选框,当我向下滚动时,这些复选框在屏幕上可见,当剩余的复选框可见时,下次它会显示另外 5 个复选框值 问题在于 BindViewHolder。此方法仅执行 recyclerView 正在获取其列表项的数据以显示(可见)。在您的情况下,如果 15 个复选框在不滚动的情况下可见,则意味着只有 15 次 BindViewHolder 被调用和执行。当您向下滚动以查看剩余的 5 个项目时,比 BindViewHolder 再调用 5 次。所以,这就是问题所在。我已经编辑了我的代码来修复这个尝试..

以上是关于在回收站视图中滚动时,它向选定的复选框列表添加了一些其他值的主要内容,如果未能解决你的问题,请参考以下文章

滚动时,在recyclerView中取消选中复选框

在顶部添加新项目后,回收器视图未滚动到顶部,因为尚未发生对列表适配器的更改

可扩展列表视图回收问题

当我在 Android 上滚动列表视图时复选框未选中

列表视图滚动时复选框自动调用onCheckedChange?

能够滚动无休止的循环回收器视图,但无法单击特定列表项