【问题标题】:RecyclerView checks wrong items as i scroll down当我向下滚动时,RecyclerView 检查错误的项目
【发布时间】:2017-09-14 20:14:48
【问题描述】:

我决定使用 RecyclerView 来显示我的数据列表。每个项目/行中有一个复选框、2 个 TextView 和一个 ImageView。我已经创建了我的适配器来处理所有事情,并将选中的项目添加到我的最终列表中。

问题是,当我检查一些项目并向下滚动时,一些项目会显示为已选中,而当我向上滚动之前检查的项目时,会显示为未选中。图像和文本视图都可以,但是向下和向上滚动时复选框会混乱。

这是我的适配器:

public class TeamAdapter extends RecyclerView.Adapter<TeamAdapter.MyViewHolder> {

    private Context mContext;
    private List<UserProject> UserList;
    private UserProject user;


    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        public TextView name, description;
        public CircleImageView profile_image;
        public CheckBox check;

        public MyViewHolder(View view) {
            super(view);
            name = (TextView) view.findViewById(R.id.name);
            description = (TextView) view.findViewById(R.id.description);
            profile_image = (CircleImageView) view.findViewById(R.id.profile_image);
            check = (CheckBox) view.findViewById(R.id.check);
        }
        @Override
        public void onClick(View v) {
            if (mItemClickListener != null) {
                mItemClickListener.onItemClickListener(v, getAdapterPosition());
            }
        }
    }


    public TeamAdapter(Context mContext, List<UserProject> userList) {
        this.mContext = mContext;
        this.UserList = userList;

    }
    @Override
    public TeamAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.adapter_teams, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final TeamAdapter.MyViewHolder holder, final int position) {

        user = UserList.get(position);

        holder.name.setText(user.getName());
        holder.description.setText(user.getCompany());

        if(user.getImageURL() != null && !user.getImageURL().isEmpty()) {
            Picasso.with(mContext).load(user.getImageURL()).into(holder.profile_image);
        }

        holder.check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    ActivityTeams.newList.add(UserList.get(position));
                }else {
                    ActivityTeams.newList.remove(UserList.get(position));
                }
            }
        });

    }


    @Override
    public int getItemCount() {
        return UserList.size();
    }

    private TeamAdapter.onRecyclerViewItemClickListener mItemClickListener;

    public void setOnItemClickListener(TeamAdapter.onRecyclerViewItemClickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }

    public interface onRecyclerViewItemClickListener {
        void onItemClickListener(View view, int position);
    }
}

【问题讨论】:

标签: android android-recyclerview


【解决方案1】:

在关于重复答案的评论中,您的持有者保留了复选框视图。您只需要根据您的支持数据更新复选框状态。

onBindViewHolder 中分配检查侦听器之前添加:

holder.check.setOnCheckedChangeListener(null);    
holder.check.setChecked(ActivityTeams.newList.contains(UserList.get(position));
holder.check.setOnCheckedChangeListener(new ... "you know what to do here"

基于此处https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/CompoundButton.javasetChecked的CompoundButton源代码:

/**
 * <p>Changes the checked state of this button.</p>
 *
 * @param checked true to check the button, false to uncheck it
 */
@Override
public void setChecked(boolean checked) {
    if (mChecked != checked) {
        mCheckedFromResource = false;
        mChecked = checked;
        refreshDrawableState();
        notifyViewAccessibilityStateChangedIfNeeded(
                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);

        // Avoid infinite recursions if setChecked() is called from a listener
        if (mBroadcasting) {
            return;
        }

        mBroadcasting = true;
        if (mOnCheckedChangeListener != null) {
            mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
        }
        if (mOnCheckedChangeWidgetListener != null) {
            mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
        }
        final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
        if (afm != null) {
            afm.notifyValueChanged(this);
        }

        mBroadcasting = false;
    }
}

如您所见,调用 setChecked 也会调用当前附加的侦听器。

【讨论】:

  • 感谢您的回复。我将此行添加到适配器,现在它不再随机检查,但当我向下滚动和备份时,它会不断将项目添加到我的列表中。
  • 我的意思是,重复添加。
  • 希望您在我编辑之前忽略我的评论。要优化监听器的设置需要更多的工作,请忽略该部分。你也没有实现对吗?因为它被破坏了错误的代码。
  • 我只在 setOnCheckedChangeListener 方法之后添加了这一行:holder.check.setChecked(ActivityTeams.newList.contains(UserList.get(position));
  • 我设法通过仅在列表中添加一个新对象(如果它还没有的话)来解决这个问题。谢谢你的回答,对我有帮助!
【解决方案2】:

您没有在 onBindViewHolder() 方法中指定是否选中 CheckBox。因此,RecyclerView 无法知道在创建/回收视图时是否检查了 CheckBox。

您可以尝试将每个相应 CheckBox 的选中/未选中状态保存在单独的 ArrayList 中,或者与您的 UserProject 类合并并将信息保留在那里。

之后,您可以简单地说 holder.check.setChecked(...); 其中 ... 是 CheckBox 的条件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    相关资源
    最近更新 更多