I have a RecyclerView list of CardViews. Each CardView has a CheckBox that the user can select/de-select. The initial selection launches a Contextual Action Bar. When I select a CheckBox and then scroll down, other CheckBoxes are also being selected. I understand that the ViewHolders are being re-used but don't know how to set the CheckBox state correctly so that onBindViewHolder updates properly. What am I missing here?
Please note that I do not want to set up a ClickListener in onBindViewHolder.
MainActivity.java
public class MainActivity extends AppCompatActivity implements
RecyclerItemClickListener {
private ArrayList<ListItem> allList;
boolean isMultiSelect = false; // for the Contextual Action Bar status
private ActionMode mActionMode;
ArrayList<ListItem> multiselect_list = new ArrayList<>();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
...
// method from the Adapter, the ItemHolder's onClick()
public void onCheckBoxClick(View view, int position) {
if (!isMultiSelect) {
multiselect_list = new ArrayList<>();
isMultiSelect = true;
if (mActionMode == null) {
mActionMode = startSupportActionMode(actionModeCallback);
}
}
multi_select(position);
}
public void multi_select(int position) {
if (mActionMode != null) {
// If a CardView with a CheckBox already selected is clicked on, then the
// Checkbox is unselected, the position is removed from the multiselect_list
// and the size of the list is decremented by +1.
if (multiselect_list.contains(allList.get(position))) {
multiselect_list.remove(allList.get(position));
}
else {
// If an empty CheckBox on a CardView is clicked on, then the position is added to the
// multiselect_list and the size of the list is incremented by +1.
multiselect_list.add(allList.get(position));
}
if (multiselect_list.size() == 1) {
mActionMode.setTitle("1 selected");
}
else if (multiselect_list.size() >= 2) {
mActionMode.setTitle(multiselect_list.size() + " selected");
}
else if (multiselect_list.size() == 0) {
mActionMode.finish();
}
refreshAdapter();
}
}
public void refreshAdapter() {
adapter.selectedItemsList = multiselect_list;
adapter.mListItems = allList;
adapter.notifyDataSetChanged();
}
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
Menu context_menu;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_action_mode, menu);
context_menu = menu;
return true;
}
...
}
Adapter.java
public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public ArrayList<ListItem> mListItems;
private Context mContext;
private RecyclerItemClickListener recyclerItemClickListener;
public ArrayList<ListItem> selectedItemsList = new ArrayList<>();
public MyRecylerAdapter(Context context, ArrayList<ListItem> listItems, ArrayList<ListItem> selectedList) {
this.mContext = context;
this.mListItems = listItems;
this.selectedItemsList = selectedList;
}
private class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private CheckBox chkSelected;
private ItemHolder(final View itemView) {
super(itemView);
chkSelected = (CheckBox) itemView.findViewById(R.id.chkSelected);
chkSelected.setOnClickListener(this);
}
public void onClick(View v) {
int adapterPos = getAdapterPosition();
// send data to MainActivity() for starting CAB.
if (recyclerItemClickListener !=null) {
recyclerItemClickListener.onCheckBoxClick(v, adapterPos);
}
}
// not sure how to reference adapter position to set the checked state here
void bind(int position) {
boolean isChecked = chkSelected.isChecked();
if (isChecked) {
chkSelected.setChecked(true);
}
else {
chkSelected.setChecked(false);
}
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
final ItemHolder itemHolder = new ItemHolder(view);
...
return itemHolder;
}
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final ListItem listItem = mListItems.get(position);
final ItemHolder itemHolder = (ItemHolder) holder;
itemHolder.bind(position);
...
}
Aucun commentaire:
Enregistrer un commentaire