RecyclerView with checkbox checked/unchecked automatically when I am scrolling

左心房为你撑大大i 提交于 2019-12-11 11:52:44

问题


this is my QuestionHolder:

 private class QuestionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private JSONObject question;
    private CheckBox checkBox;
    private TextView question_txt;
    public QuestionHolder(final LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.question_item, parent, false));

        checkBox  = (CheckBox) itemView.findViewById(R.id.question_checkbox);

        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //try {
                    //Toast.makeText(getActivity(), "ID: " + question.get("_id"), Toast.LENGTH_SHORT).show();
                //} catch (JSONException e) { }
                // TODO: If this was checked then add the question's id to the answered list
            }
        });
        question_txt = (TextView) itemView.findViewById(R.id.question);
        itemView.setOnClickListener(this);
    }

here I am binding the questiontxt:

public void bind(JSONObject question) {
  this.question = question;
  try {
    question_txt.setText(question.getString("_question"));
  } catch (JSONException je) { }
}

@Override
public void onClick(View v) {
  // TODO: If this was checked then add the question's id to the answered list
}
}

this is my Adapter which extend QuestionHolder:

private class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {

    private JSONArray questions;

    public QuestionAdapter(JSONArray questions) {
        this.questions = questions;
    }

    @Override
    public QuestionHolder onCreateViewHolder(ViewGroup parent, int viewType) 
{
        return new QuestionHolder(LayoutInflater.from(getActivity()), parent);
    }

this is onBindViewHolder:

@Override
public void onBindViewHolder(QuestionHolder holder, int position) {
  try {
    final JSONObject question = questions.getJSONObject(position);
    holder.bind(question);
  } catch (JSONException je) { }
}

@Override
public int getItemCount() {
  return questions.length();
}
}

this is QuestionHolder:

private class QuestionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private JSONObject question;
    private CheckBox checkBox;
    private TextView question_txt;
    public QuestionHolder(final LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.question_item, parent, false));

        checkBox  = (CheckBox) itemView.findViewById(R.id.question_checkbox);

        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //try {
                    //Toast.makeText(getActivity(), "ID: " + question.get("_id"), Toast.LENGTH_SHORT).show();
                //} catch (JSONException e) { }
                // TODO: If this was checked then add the question's id to the answered list
            }
        });
        question_txt = (TextView) itemView.findViewById(R.id.question);
        itemView.setOnClickListener(this);
    }

    public void bind(JSONObject question) {
        this.question = question;
        try {
            question_txt.setText(question.getString("_question"));
        } catch (JSONException je) { }
    }

    @Override
    public void onClick(View v) {
        // TODO: If this was checked then add the question's id to the answered list
    }
}

回答1:


This is because your ViewHolder is recycled when scrolling. So, you need to keep the state of the CheckBox for each item position. You can use SparseBooleanArray to handle this.

You can do something like this:

private class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {

  SparseBooleanArray checkedItems = new SparseBooleanArray();

  ...

  @Override
  public void onBindViewHolder(QuestionHolder holder, int position) {
    try {
      final JSONObject question = questions.getJSONObject(position);

      // Remember to change access modifier of checkBox in your ViewHolder
      // Get the state from checkedItems. If no previous value, it will return false.
      holder.checkBox.setChecked(checkedItems.get(position));

      // This is a sample. Do not use create listener here.
      checkBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          // save the check state
          checkedItems.put(position, true);
        }

      holder.bind(question);
    } catch (JSONException je) { }
  }

  ...

}



回答2:


RecyclerView removes (recycles) the unseen views from the layout on scrolling, this is the basic behavior of recyclerView in order to reduce memory use.

So when a view with a checkbox is "recycled", a checked checkbox gets unchecked and if it has a listener, the listener gets called.

You can remove the listener from the view when it is recycled. Just override the onViewRecycled method.

 @Override
    public void onViewRecycled(@NonNull MyViewHolder holder) {
        if (holder.checkBox != null) {
            holder.checkBox.setOnClickListener(null);
        }
        super.onViewRecycled(holder);
    }

When the view is constructed again, while scrolling, your listener will also be added again.



来源:https://stackoverflow.com/questions/48474219/recyclerview-with-checkbox-checked-unchecked-automatically-when-i-am-scrolling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!