如果我 select RecyclerView 项目中的一个按钮,按钮将被自动点击
Button is auto clicked if I select one button in RecyclerView item
在我的 RecyclerView
项目中,有一个按钮和其他视图。单击按钮时我隐藏了按钮。问题是,如果我点击第一项的按钮,第八项的按钮会自动点击,如果我点击第二项的按钮,第九项的按钮会自动点击等等。如何解决这个问题?
适配器class:
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private List<Model> models;
Model model;
// public MyAdapterListener onClickListener;
SparseBooleanArray mStateButtons = new SparseBooleanArray();
public Adapter(List<Model> models){
this.models = models;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
String question = models.get(position).getQues();
final String optA = models.get(position).getOptA();
final String optB = models.get(position).getOptB();
final String optC = models.get(position).getOptC();
final String optD = models.get(position).getOptD();
final String answer = models.get(position).getAns();
holder.question.setText(question);
holder.optA.setText(optA);
holder.optB.setText(optB);
holder.optC.setText(optC);
holder.optD.setText(optD);
holder.options.setTag(position);
holder.options.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int radioButtonID = group.getCheckedRadioButtonId();
int clickedPos = (Integer) group.getTag();
models.get(clickedPos).setChecked(radioButtonID);
}
});
holder.options.check(models.get(position).getChecked());
final int currentPosition = holder.getAdapterPosition();
final Button button = holder.seeAnswer;
if(mStateButtons.valueAt(currentPosition)) {
button.setVisibility(View.GONE);
} else {
button.setVisibility(View.VISIBLE);
}
holder.seeAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mStateButtons.put(position, true);
}
});
}
@Override
public int getItemCount() {
return Models.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
TextView question;
RadioButton optA, optB, optC, optD;
Button seeAnswer;
RadioGroup options;
public ViewHolder(View itemView) {
super(itemView);
options = (RadioGroup) itemView.findViewById(R.id.rgMcqOptions);
question = (TextView) itemView.findViewById(R.id.tvMcqQues);
optA = (RadioButton) itemView.findViewById(R.id.rbOptA);
optB = (RadioButton) itemView.findViewById(R.id.rbOptB);
optC = (RadioButton) itemView.findViewById(R.id.rbOptC);
optD = (RadioButton) itemView.findViewById(R.id.rbOptD);
seeAnswer = (Button) itemView.findViewById(R.id.btnSeeAnswer);
}
}
}
问题似乎是您没有正确初始化 Button
的状态。 RecyclerView
中的单元格在出现或隐藏在屏幕中时会被重复使用。这意味着如果您隐藏第一个位置,然后回收此视图以创建第 8 个位置,Button
将保持其状态,在本例中为 INVISIBLE
尝试为所有情况分配一个值或将值初始化为 VISIBLE
。
这通常是因为您忘记保留 Button 的状态以防它被回收。您可以使用 SparseBooleanArray
来存储状态。像这样:
public class YourAdapter ... {
// variable to save the state of buttons.
// we use state true as hidden, false as visible
SparseBooleanArray mStateButtons = new SparseBooleanArray();
...
@Override
public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {
final int currentPosition = viewHolder.getAdapterPosition();
// assume this is your button
Button button = viewHolder.yourButton;
// set the previous state to button
if(mStateButtons.valueAt(currentPosition)) {
// state is true, so the button need to be hide.
button.setVisibility(View.GONE);
} else {
// default value is valse, which is we set as visible.
button.setVisibility(View.VISIBLE);
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// save the state when clicked
mStateButtons.put(currentPosition, true);
}
});
}
}
更新
尝试移动 ViewHolder 上的点击处理,如下所示:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
...
Button seeAnswer;
public ViewHolder(View itemView) {
super(itemView);
...
seeAnswer = (Button) itemView.findViewById(R.id.btnSeeAnswer);
itemView.setOnClickListener(this);
}
// Handles the row being being clicked
@Override
public void onClick(View view) {
mStateButtons.put(getAdapterPosition(), true);
view.setVisibility(View.GONE);
}
}
然后删除 onBindViewHolder
中的 button.setOnClickListener(new View.OnClickListener()
。
您需要一些方法来跟踪哪些按钮应该隐藏,哪些不应该。这是您的适配器的责任,因此您需要添加某种形式的数组来跟踪那里的按钮状态。 SparseBooleanArray
是一个有效且合适的选项:
private SparseBooleanArray hideButtons = new SparseBooleanArray();
在onBindView
中您需要更新当前绑定项目的视图,包括更新按钮可见性:
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
holder.seeAnswer.setVisibility( hideButtons.get(position, false) ? View.GONE : View.VISIBLE );
...
}
当然,您需要实际设置可见性 - 并在单击按钮时将其存储在 SparseBooleanArray
中。将此事件处理程序放在 ViewHolder
中是一个不错的选择:
class ViewHolder extends RecyclerView.ViewHolder{
Button seeAnswer;
...
ViewHolder(View itemView) {
super(itemView);
seeAnswer = (Button) itemView.findViewById(R.id.btnSeeAnswer);
seeAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
seeAnswer.setVisibility(View.GONE);
hideButtons.put(getAdapterPosition(), true);
}
});
...
}
}
这是一个经过测试和验证的解决方案,因此如果您按照此进行操作但仍然不起作用,则问题的原因在其他地方。
在我的 RecyclerView
项目中,有一个按钮和其他视图。单击按钮时我隐藏了按钮。问题是,如果我点击第一项的按钮,第八项的按钮会自动点击,如果我点击第二项的按钮,第九项的按钮会自动点击等等。如何解决这个问题?
适配器class:
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private List<Model> models;
Model model;
// public MyAdapterListener onClickListener;
SparseBooleanArray mStateButtons = new SparseBooleanArray();
public Adapter(List<Model> models){
this.models = models;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_row, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
String question = models.get(position).getQues();
final String optA = models.get(position).getOptA();
final String optB = models.get(position).getOptB();
final String optC = models.get(position).getOptC();
final String optD = models.get(position).getOptD();
final String answer = models.get(position).getAns();
holder.question.setText(question);
holder.optA.setText(optA);
holder.optB.setText(optB);
holder.optC.setText(optC);
holder.optD.setText(optD);
holder.options.setTag(position);
holder.options.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int radioButtonID = group.getCheckedRadioButtonId();
int clickedPos = (Integer) group.getTag();
models.get(clickedPos).setChecked(radioButtonID);
}
});
holder.options.check(models.get(position).getChecked());
final int currentPosition = holder.getAdapterPosition();
final Button button = holder.seeAnswer;
if(mStateButtons.valueAt(currentPosition)) {
button.setVisibility(View.GONE);
} else {
button.setVisibility(View.VISIBLE);
}
holder.seeAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mStateButtons.put(position, true);
}
});
}
@Override
public int getItemCount() {
return Models.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
TextView question;
RadioButton optA, optB, optC, optD;
Button seeAnswer;
RadioGroup options;
public ViewHolder(View itemView) {
super(itemView);
options = (RadioGroup) itemView.findViewById(R.id.rgMcqOptions);
question = (TextView) itemView.findViewById(R.id.tvMcqQues);
optA = (RadioButton) itemView.findViewById(R.id.rbOptA);
optB = (RadioButton) itemView.findViewById(R.id.rbOptB);
optC = (RadioButton) itemView.findViewById(R.id.rbOptC);
optD = (RadioButton) itemView.findViewById(R.id.rbOptD);
seeAnswer = (Button) itemView.findViewById(R.id.btnSeeAnswer);
}
}
}
问题似乎是您没有正确初始化 Button
的状态。 RecyclerView
中的单元格在出现或隐藏在屏幕中时会被重复使用。这意味着如果您隐藏第一个位置,然后回收此视图以创建第 8 个位置,Button
将保持其状态,在本例中为 INVISIBLE
尝试为所有情况分配一个值或将值初始化为 VISIBLE
。
这通常是因为您忘记保留 Button 的状态以防它被回收。您可以使用 SparseBooleanArray
来存储状态。像这样:
public class YourAdapter ... {
// variable to save the state of buttons.
// we use state true as hidden, false as visible
SparseBooleanArray mStateButtons = new SparseBooleanArray();
...
@Override
public void onBindViewHolder(ContactsAdapter.ViewHolder viewHolder, int position) {
final int currentPosition = viewHolder.getAdapterPosition();
// assume this is your button
Button button = viewHolder.yourButton;
// set the previous state to button
if(mStateButtons.valueAt(currentPosition)) {
// state is true, so the button need to be hide.
button.setVisibility(View.GONE);
} else {
// default value is valse, which is we set as visible.
button.setVisibility(View.VISIBLE);
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// save the state when clicked
mStateButtons.put(currentPosition, true);
}
});
}
}
更新
尝试移动 ViewHolder 上的点击处理,如下所示:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
...
Button seeAnswer;
public ViewHolder(View itemView) {
super(itemView);
...
seeAnswer = (Button) itemView.findViewById(R.id.btnSeeAnswer);
itemView.setOnClickListener(this);
}
// Handles the row being being clicked
@Override
public void onClick(View view) {
mStateButtons.put(getAdapterPosition(), true);
view.setVisibility(View.GONE);
}
}
然后删除 onBindViewHolder
中的 button.setOnClickListener(new View.OnClickListener()
。
您需要一些方法来跟踪哪些按钮应该隐藏,哪些不应该。这是您的适配器的责任,因此您需要添加某种形式的数组来跟踪那里的按钮状态。 SparseBooleanArray
是一个有效且合适的选项:
private SparseBooleanArray hideButtons = new SparseBooleanArray();
在onBindView
中您需要更新当前绑定项目的视图,包括更新按钮可见性:
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
holder.seeAnswer.setVisibility( hideButtons.get(position, false) ? View.GONE : View.VISIBLE );
...
}
当然,您需要实际设置可见性 - 并在单击按钮时将其存储在 SparseBooleanArray
中。将此事件处理程序放在 ViewHolder
中是一个不错的选择:
class ViewHolder extends RecyclerView.ViewHolder{
Button seeAnswer;
...
ViewHolder(View itemView) {
super(itemView);
seeAnswer = (Button) itemView.findViewById(R.id.btnSeeAnswer);
seeAnswer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
seeAnswer.setVisibility(View.GONE);
hideButtons.put(getAdapterPosition(), true);
}
});
...
}
}
这是一个经过测试和验证的解决方案,因此如果您按照此进行操作但仍然不起作用,则问题的原因在其他地方。