I have an action item called delete, which gets an ArrayList that I have created and removes all the Contacts that are checked (based on a boolean variable that I have in the class Contact).
Everything is good when I click delete and it's one item, but if it's more than 6 items, onDestroyActionMode method interrupts my onActionItemClicked method and some items are left not deleted. How do I solve this?
Here is my code:
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class ContactViewAdapter extends RecyclerView.Adapter<ContactViewAdapter.ContactViewHolder> {
private static final String TAG = "AKS";
private AppCompatActivity mActivity;
private List<Contact> contactList;
public ActionMode mActionMode = null;
public ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.action_mode_menu, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_mode_delete:
for (int i = 0; i < contactList.size(); i++) {
Log.d(TAG, "size " + String.valueOf(contactList.size()));
if (contactList.get(i).isSelected) {
contactList.remove(i);
}
}
notifyDataSetChanged();
mode.finish();
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
for (Contact c : contactList) {
c.isSelected = false;
Log.d(TAG, "onDestroyActionMode");
}
mActionMode.finish();
mActionMode = null;
notifyDataSetChanged();
}
};
public class ContactViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public TextView contactName;
public TextView contactMoneyOwed;
public ImageView contactPhoto;
public CheckBox isCheckedBox;
public ContactViewHolder(View v) {
super(v);
contactName = (TextView) itemView.findViewById(R.id.contact_name);
contactMoneyOwed = (TextView) itemView.findViewById(R.id.contact_money_owed);
contactPhoto = (ImageView) itemView.findViewById(R.id.contact_photo);
isCheckedBox = (CheckBox) itemView.findViewById(R.id.listItemCheckBox);
v.setOnClickListener(this);
v.setOnLongClickListener(this);
}
@Override
public void onClick(View v) {
boolean everythingIsUnchecked = true;
for (Contact c : contactList) {
if (c.isSelected) {
everythingIsUnchecked = false;
}
}
if (!everythingIsUnchecked) {
isCheckedBox.setChecked(!isCheckedBox.isChecked());
} else {
Toast.makeText(mActivity.getApplicationContext(), "Coming soon!", Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onLongClick(View v) {
isCheckedBox.setChecked(true);
return true;
}
}
public ContactViewAdapter(List<Contact> contactList, AppCompatActivity activity) {
this.contactList = contactList;
this.mActivity = activity;
}
@Override
public ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
return new ContactViewHolder(v);
}
@Override
public void onBindViewHolder(final ContactViewHolder contactViewHolder, final int position) {
contactViewHolder.contactName.setText(contactList.get(position).name);
contactViewHolder.contactMoneyOwed.setText(contactList.get(position).moneyOwed);
contactViewHolder.contactPhoto.setImageResource(contactList.get(position).photoID);
contactViewHolder.contactPhoto.setOnTouchListener(null);
contactViewHolder.contactPhoto.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
contactViewHolder.isCheckedBox.setChecked(true);
}
return true;
}
});
contactViewHolder.isCheckedBox.setOnCheckedChangeListener(null);
contactViewHolder.isCheckedBox.setChecked(contactList.get(position).isSelected);
if (contactViewHolder.isCheckedBox.isChecked()) {
contactViewHolder.contactPhoto.setVisibility(View.GONE);
contactViewHolder.isCheckedBox.setVisibility(View.VISIBLE);
} else {
contactViewHolder.isCheckedBox.setVisibility(View.GONE);
contactViewHolder.contactPhoto.setVisibility(View.VISIBLE);
}
contactViewHolder.isCheckedBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.d(TAG, String.valueOf(position));
contactList.get(position).isSelected = isChecked;
boolean everythingIsUnchecked = true;
for (Contact c : contactList) {
if (c.isSelected) {
everythingIsUnchecked = false;
}
}
if (mActionMode == null) {
mActionMode = mActivity.startActionMode(mActionModeCallback);
} else if (everythingIsUnchecked) {
mActionMode.finish();
mActionMode = null;
}
if (isChecked) {
contactViewHolder.contactPhoto.setVisibility(View.GONE);
contactViewHolder.isCheckedBox.setVisibility(View.VISIBLE);
} else {
contactViewHolder.isCheckedBox.setVisibility(View.GONE);
contactViewHolder.contactPhoto.setVisibility(View.VISIBLE);
}
}
});
}
@Override
public int getItemCount() {
return contactList.size();
}
}
And here's what I get from the log:
10-03 19:47:23.181 1962-1962/com.example.andreassavva.expensemanager D/AKS: 0
10-03 19:47:23.413 1962-1962/com.example.andreassavva.expensemanager D/AKS: 1
10-03 19:47:23.789 1962-1962/com.example.andreassavva.expensemanager D/AKS: 2
10-03 19:47:24.067 1962-1962/com.example.andreassavva.expensemanager D/AKS: 3
10-03 19:47:24.453 1962-1962/com.example.andreassavva.expensemanager D/AKS: 4
10-03 19:47:25.115 1962-1962/com.example.andreassavva.expensemanager D/AKS: 5
10-03 19:47:26.350 1962-1962/com.example.andreassavva.expensemanager D/AKS: 6
10-03 19:47:26.734 1962-1962/com.example.andreassavva.expensemanager D/AKS: 7
10-03 19:47:27.046 1962-1962/com.example.andreassavva.expensemanager D/AKS: 8
10-03 19:47:27.468 1962-1962/com.example.andreassavva.expensemanager D/AKS: 9
10-03 19:47:27.812 1962-1962/com.example.andreassavva.expensemanager D/AKS: 10
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 11
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 10
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 9
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 8
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 7
10-03 19:47:29.658 1962-1962/com.example.andreassavva.expensemanager D/AKS: size 6
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
10-03 19:47:29.659 1962-1962/com.example.andreassavva.expensemanager D/AKS: onDestroyActionMode
Figured it out. My for-loop sucks. I needed to change it to
for (int i = contactList.size() - 1; i >= 0; i--) {
if (contactList.get(i).isSelected()) {
contactList.remove(i);
}
}
instead. Thanks for the help!