0

У меня есть элемент действия, называемый delete, который получает ArrayList, который я создал, и удаляет все проверенные контакты (на основе логической переменной, которую я имею в классе Contact).OnDestroyActionMode() прерван onActionItemClicked()

Все хорошо, когда я нажимаю delete, и это один элемент, но если это более 6 элементов, метод onDestroyActionMode прерывает мой метод onActionItemClicked, а некоторые элементы остаются не удаляемыми. Как я могу это решить?

Вот мой код:

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(); 
    } 

} 

И вот что я получаю из журнала:

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 

ответ

0

Фигурные его. Моя петля засасывает. Мне нужно было изменить его на

for (int i = contactList.size() - 1; i >= 0; i--) { 
         if (contactList.get(i).isSelected()) { 
          contactList.remove(i); 
         } 
        } 

вместо этого. Спасибо за помощь!

+0

Соблюдайте особую осторожность при удалении предметов из коллекции во время итерации по ней. Вы можете использовать «Итератор», чтобы сделать это безопасно, сохраняя порядок итераций. Ваше решение повторяется с конца списка. См. Править. –

+0

Почему хуже начинать с конца списка? –

+0

Я этого никогда не говорил. Используйте «Итератор», если вы хотите начать с начала списка. Ваш оригинал для этого. Думал, что вы можете сохранить это поведение. –

0

ActionMode.finish() звонки onDestroyActionMode(). Поэтому удалите вызов finish() из вашей реализации onDestroyActionMode(). Новая реализация становится:

@Override 
public void onDestroyActionMode(ActionMode mode) { 
    for (Contact c : contactList) { 
     c.isSelected = false; 
     Log.d(TAG, "onDestroyActionMode"); 
    } 
    //mActionMode.finish(); 
    mActionMode = null; 
    notifyDataSetChanged(); 
} 

Поскольку вы звоните notifyDataSetChanged() в onDestroyActionMode(), удалите этот вызов с вашего осуществления onActionItemClicked(). Новая onActionItemClicked() реализация становится:

EDIT:

@Override 
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 

     switch (item.getItemId()) { 
      case R.id.action_mode_delete: 
      Iterator<Contact> contactIterator = contactList.iterator(); 
       while(contactIterator.hasNext()) { 
        Contact contact = contactIterator.next(); 
        if (contact.isSelected) { 
        contactIterator.remove(); 
        } 
       } 
       //notifyDataSetChanged(); 

       mode.finish();// This calls 'onDestroyActionMode()' 
       // and it will notify the data set change. 
       return true; 
      default: 
       return false; 
     } 
    } 
+0

Сделал это, все еще не работает, onDestroyActionMode() по-прежнему называется! Кажется, что onDestroyActionMode() вызывается во время цикла for, поэтому он прерывает вызываемый цикл for. Любые идеи относительно того, почему это происходит? –

Смежные вопросы