RecyclerView索引中的复选框被点击两次

问题描述 投票:1回答:4

我在RecyclerViewCheckBoxCardView列表,使用简单的onClickListener。但是当点击索引0时,索引10也会显示为已点击。如果点击指数1同样是11,索引2也是12,依此类推。我该如何解决这个问题?

android checkbox android-recyclerview
4个回答
0
投票

解决它的三个步骤,可以在任何有复选框小部件的地方使用,它将被重新启动。

首先,每个适配器都有一个相应的'bean'绑定它。例如,List,T是bean。

其次,在'bean'类中添加一个布尔字段'ischecked'。

最后,使用此字段可以在recyclelerview重新使用复选框时重置复选框的状态,并在复选框的状态更改时更新它。


0
投票

RecyclerView将在滚动时重复使用前一行的布局,因此如果您检查项目1并滚动,项目11仍将被检查,除非被告知不是。

onBindViewHolder中,您希望将布局设置为您正在显示的对象的当前状态。

例如,假设我们有一个Dogs列表,我们可以标记我们是否宠爱了Dog

class Dog {
    public boolean hasPet = false;
    public String name;
}

现在,如果您要显示每个Dog,您可以这样做。

void onBindViewHolder(MyViewHolder holde, int position) {
    Dog dog = list[position];
    holder.name = dog.name;

    // Remove any onCheckChangeListener or else we'll change the previously rendered dog.
    holder.check.setOnCheckedChangeListener(null);

    // Set the checkbox to the current state of the dog.
    holder.check.setChecked(dog.hasPet);

    // Add a new onCheckChangeListener with the current dog.
    holder.check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Logger.d("Clicked.");
            dog.hasPet = isChecked;
        }
    });
}

0
投票

这是因为你的RecyclerView的行为。 RecyclerView尝试回收已经生成的视图,只需对数据进行最小的更改。因此,为了在列表项中精确填充数据,您需要准确说明需要显示的内容。

在您的情况下,您需要保持复选框的轨道单击某处(可能在不同的数组中),以便您可以相应地填充视图。让我们考虑以下代码。

// Let us create an integer array having the same size of your list that is being passed to your RecyclerView
// Initially, all elements in the array is zero. 
private int[] array = new int[yourList.size()]; 

现在在你的onBindViewHolder,我想你已经为你的onClickListener实施了CheckBox。因此,当您单击CheckBox时,将array中的相应元素设置为1

public void onClick(int position) {
    // Checbox click action here
    if (array[position] == 0) 
        array[position] = 1; // Use the position of your adapter to set the value.
    else array[position] = 0; // Toggle the values on check/uncheck
}

现在在填充onBindViewHolderCheckBox中,检查其在array中的位置值并相应地设置检查状态。

if(array[position] == 1) checkBox.setChecked(true);
else checkBox.setChecked(false);

希望有所帮助!


0
投票

问题是因为您没有保留每个项目的点击状态。您可以修改pojo并添加check state属性,或者只需使用SparseBooleanArray来保存所有项目的检查状态。

这里是使用SparseBooleanArray的示例。

假设我们正在使用User的简单pojo:

public class User {
    private String id;
    private String name;
    // constructor, setter, getter
}

首先,创建一个SparseBooleanArray来保存所选的标志,如下所示:

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {

    private List<User> mUsers;
    private SparseBooleanArray mSelectedFlags;

    public UserAdapter(List<User> users) {
        mUsers = users;
        mSelectedFlags = new SparseBooleanArray();
    }

    ...
}

其次,每当你单击ViewHolder中的CheckBox时保存状态:

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvName;
        public TextView tvId;
        public CheckBox cbxSelect;

        public ViewHolder(View itemView) {

            super(itemView);

            ...
            // bind view here

        cbxSelect.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // set the state for specific item by its position.
                mSelectedFlags.put(getAdapterPosition()), isChecked);
            }

        });
    }

最后,在onBindViewHolder中设置状态:

    @Override
    public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {

        int itemPosition = viewHolder.getAdapterPosition();
        User user = mUsers.get(itemPosition);

        viewHolder.tvId.setText(user.getId());
        viewHolder.tvName.setText(user.getName());

        // set the check state for each item
        // SparseBooleanArray will return false as default value
        viewHolder.cbxSelect.setChecked(mFlagSelected.get(itemPosition));

    }

完整的适配器将是这样的:

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {

    private List<User> mUsers;
    private SparseBooleanArray mSelectedFlags;

    public UserAdapter(List<User> users) {
        mUsers = users;
        mSelectedFlags = new SparseBooleanArray();
    }

    @Override
    public UserAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        ...
        // inflate and return view holder.
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {

        int itemPosition = viewHolder.getAdapterPosition();
        User user = mUsers.get(itemPosition);

        viewHolder.tvId.setText(user.getId());
        viewHolder.tvName.setText(user.getName());

        // set the check state for each item
        // SparseBooleanArray will return false as default value
        viewHolder.cbxSelect.setChecked(mFlagSelected.get(itemPosition));

    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView tvName;
        public TextView tvId;
        public CheckBox cbxSelect;

        public ViewHolder(View itemView) {

            super(itemView);

            ...
            // bind view here

        cbxSelect.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // set the state for specific item by its position.
                mSelectedFlags.put(getAdapterPosition()), isChecked);
            }

        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.