我有一个RecyclerView
列表,其中的CheckBox
中的CardView
使用了简单的onClickListener
。但是,当单击索引0
时,索引10
也显示为单击。如果单击了索引1
,则同样,单击11
,单击索引2
,也单击12
,依此类推。我该如何解决这个问题?
答案 0 :(得分: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
}
现在在填充onBindViewHolder
时进入CheckBox
,检查其在array
中的位置值,并相应地设置检查状态。
if(array[position] == 1) checkBox.setChecked(true);
else checkBox.setChecked(false);
希望有帮助!
答案 1 :(得分: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;
}
});
}
答案 2 :(得分:0)
解决此问题的三个步骤,可以在任何具有复选框小部件的地方使用,然后将继续使用它。
首先,每个适配器都有一个对应的“ bean”绑定到它。例如List,T是bean。
第二,在'bean'类中添加一个'ischecked'布尔字段。
最后,使用此字段可在recycleview重用复选框时重置复选框的状态,并在更改复选框状态时进行更新。
答案 3 :(得分:0)
问题是因为您没有保持每个项目的点击状态。您可以修改pojo并添加检查状态属性,也可以简单地使用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
中的复选框时,保存状态:
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);
}
});
}
}