如果我 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);
            }
        });

        ...
    }

}

这是一个经过测试和验证的解决方案,因此如果您按照此进行操作但仍然不起作用,则问题的原因在其他地方。