5

Ich habe eine kontextabhängige Aktionsleiste in einem verschachtelten Fragment implementiert. Dieses Fragment ist Teil eines View Pagers und der View Pager ist ebenfalls ein Fragment und Teil eines Navigations-Drawers.kontextueller Aktionsmodus im Fragment - schließen, wenn nicht fokussiert?

Mein Problem: Ich möchte die Kontextmenüleiste schließen, wenn das Fragment nicht mehr fokussiert ist. Wenn ich also durch den Ansichtspager wische, sollte die Aktionsmodusleiste schließen. Aber wenn ich die onPause() Methode des verschachtelten Fragments verwende, wird die Methode nicht direkt aufgerufen. Oft wartet sie, bis ich zwei oder drei Mal vorwärts geklaut ... Hier sind ein paar Bilder:

enter image description here

enter image description here

Im zweiten Bild sieht man, dass das Action-Modus Bar ist immer noch da. Meine Frage ist also: In welcher Methode sollte ich meine actionModeBar.finish() Methode aufrufen, um die Aktionsmodus-Leiste direkt zu schließen, wenn ich das Fragment verlasse?

Vielleicht ist der Code des Fragments hilft Ihnen:

public class EditorFragment extends Fragment { 

    private static final String KEY_POSITION="position"; 
    ListView listView; 
    private boolean isMultipleList = false; 
    private ActionMode acMode; 
    private int counterChecked = 0; 

    private ActionMode.Callback modeCallBack = new ActionMode.Callback() { 

    public boolean onPrepareActionMode(ActionMode mode, Menu menu){ 
      return false; 
     } 

     public void onDestroyActionMode(ActionMode mode) { 
      listView.clearChoices(); 
      for (int i = 0; i < listView.getChildCount(); i++) 
       listView.setItemChecked(i, false); 
       listView.post(new Runnable() { 
        @Override 
        public void run() { 
         listView.setChoiceMode(ListView.CHOICE_MODE_NONE); 
        } 
       }); 
      isMultipleList = false; 
      counterChecked = 0; 
      mode = null; 
     } 

     public boolean onCreateActionMode(ActionMode mode, Menu menu) { 
      mode.setTitle("1 Aufgabe"); 
      mode.getMenuInflater().inflate(R.menu.actionmode, menu); 
      return true; 
     } 

     public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 
      switch (item.getItemId()) { 
      case R.id.actionmode_delete: 
       int choiceCount = listView.getCount(); 
       SparseBooleanArray spBoolArray = listView.getCheckedItemPositions(); 

       DBAufgaben db = new DBAufgaben(MainActivity.getMContext()); 
       db.open(); 

       for (int i = 0; i < choiceCount; i++) { 
        if(spBoolArray.get(i)){ 
         db.deletContact(listView.getItemIdAtPosition(i)); 
        } 

       } 
       Cursor cursor = db.getAllRecords(); 
       AdapterEingang adapterE = new AdapterEingang(MainActivity.getMContext(), cursor, 0); 
       listView.setAdapter(adapterE); 
       db.close(); 
       mode.finish(); 
       break; 
      case R.id.actionmode_cancel: 
       mode.finish(); 
       break; 
      } 
      return false; 
     } 
    }; 

    //......// 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     View rootView = null; 
     int position = getArguments().getInt(KEY_POSITION, -1); 

     switch(position){ 
     case 0: 
      rootView = inflater.inflate(R.layout.pager_list, null); 
      listView = (ListView) rootView.findViewById(R.id.pager_list); 

      Context context = MainActivity.getMContext(); 

      DBAufgaben db = new DBAufgaben(context); 

      db.open(); 
      Cursor cursor = db.getAllRecords(); 
      AdapterEingang adapterE = new AdapterEingang(context, cursor, 0); 
      listView.setAdapter(adapterE); 
      db.close(); 

      listView.setOnItemLongClickListener(new OnItemLongClickListener(){ 



       @Override 
       public boolean onItemLongClick(AdapterView<?> adapterView, View view, 
         int position, long id) { 
        if(!isMultipleList){ 
         acMode = MainActivity.getInstance().startActionMode(modeCallBack); 
         listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
         listView.setItemChecked(position, true); 
         isMultipleList = true; 
         counterChecked++; 
         setNewTitle();      
        } else { 
         listView.setItemChecked(position, true); 
         counterChecked++; 
         setNewTitle(); 
        } 

        return true; 
       } 

       }); 
      listView.setOnItemClickListener(new OnItemClickListener(){ 

      @Override 
      public void onItemClick(AdapterView<?> adapterView, View view, int position, 
        long id) { 
       Log.d(getTag(), "Datensatz: "+String.valueOf(id)); 
       if(isMultipleList){ 
        if(listView.isItemChecked(position)){ 
         listView.setItemChecked(position, true); 
         counterChecked++; 
         setNewTitle(); 
        } else { 
         listView.setItemChecked(position, false); 
         counterChecked--; 
         setNewTitle(); 
        } 

       } 

      } 

      }); 
      break; 
     default: 
      rootView = inflater.inflate(R.layout.frag_dummy, null); 
      TextView txt = (TextView) rootView.findViewById(R.id.dummy_txt); 
      txt.setText(String.valueOf(position)); 
      break; 
     } 



     return(rootView); 
    } 
    public void setNewTitle(){ 
     if(counterChecked == 1){ 
      acMode.setTitle(counterChecked+" Aufgabe"); 
     } else { 
      acMode.setTitle(counterChecked+" Aufgaben"); 
     } 
    } 
    @Override 
    public void onPause(){ 
     super.onPause(); 
     if(isMultipleList){ 
      acMode.finish(); 
     } 
    } 
} 

Antwort

5

ViewPagers hält mehrere Seiten aktiv zu jeder Zeit (standardmäßig die Seite vor und Seite nach der aktuell angezeigten Seite), also warum onPause() wird nicht aufgerufen, bis Sie zwei Seiten wegwischen.

Ihre beste Wette wäre, eine ViewPager.OnPageChangeListener zu verwenden, und den ActionMode in onPageSelected(..) ein- und auszublenden (d. H. Wenn die ausgewählte Seite nicht diejenige mit dem ActionMode ist, verstecken Sie den ActionMode). Sie müssen dies wahrscheinlich in der Aktivität implementieren, die Ihren ViewPager hostet.

4

Das ist für mich gearbeitet:

@Override 
public void setUserVisibleHint(boolean isVisibleToUser) { 
    if (!isVisibleToUser && this.listView != null) { 
     //HACK this is done in order to finish the contextual action bar 
     int choiceMode = this.listView.getChoiceMode(); 
     this.listView.setChoiceMode(choiceMode); 
    } 
} 
+2

Das schmutzige HACK und es ist genau das schmutzig ist, was ich brauchte. Vielen Dank. Ich hatte bereits versucht, Finish auf dem zuvor gespeicherten actionMode einfach aufzurufen –

3

ich Code aus dem OP mit der Überschreibung durch den Benutzer pomber vorgeschlagen kombiniert:

  • ich spare die ActionMode zu einem Klasse-Feld, wenn die Aktion Modus erstellt .
  • Ich setze das Feld zurück auf null, wenn der Aktionsmodus zerstört wird.
  • I überschreiben setUserVisibleHint in meinem Fragment und ActionMode#finish() aufrufen, wenn das Fragment nicht in der Ansicht Pager sichtbar ist.
  • Ich rufe auch ActionMode#finish() in der onPause() Methode des Fragments, um das Fragment zu schließen, wenn der Benutzer an anderer Stelle navigiert.

Code:

@Nullable 
ActionMode mActionMode = null; 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 

    // Start out with a progress indicator. 
    setListShownNoAnimation(false); 

    setEmptyText(getText(R.string.no_forms_in_progress)); 

    getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL); 
    getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() { 
     @Override 
     public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { 
      // Here you can do something when items are selected/de-selected, 
      // such as update the title in the CAB 
     } 

     @Override 
     public boolean onCreateActionMode(ActionMode mode, Menu menu) { 
      MenuInflater inflater = mode.getMenuInflater(); 
      inflater.inflate(R.menu.context_saved_item, menu); 
      inflater.inflate(R.menu.context_instance_list, menu); 
      mActionMode = mode; 
      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_delete: 
        confirmDelete(getListView().getCheckedItemIds()); 
        return true; 
       case R.id.action_print: 
        print(getListView().getCheckedItemIds()); 
        return true; 
      } 
      return false; 
     } 

     @Override 
     public void onDestroyActionMode(ActionMode mode) { 
      mActionMode = null; 
     } 
    }); 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    if (mActionMode != null) { 
     mActionMode.finish(); 
    } 
} 

@Override 
public void setUserVisibleHint(boolean isVisibleToUser) { 
    super.setUserVisibleHint(isVisibleToUser); 
    if (mActionMode != null && !isVisibleToUser) { 
     mActionMode.finish(); 
    } 
} 
3

Hier ist, was für mich gearbeitet -

  1. Halten Sie einen statischen Verweis auf den Aktionsmodus in MyFragment:

public static ActionMode mActionMode;

@Override 
    public boolean onCreateActionMode(ActionMode mode, Menu menu) { 
     mActionMode = mode; 
     return true; 
    } 

    @Override 
    public void onDestroyActionMode(ActionMode mode) { 
     mActionMode = null; 
    } 
  1. In MyViewPagerActivity ViewPager.OnPageChangeListener einstellen.

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
 

 
      .... 
 

 
      @Override 
 
      public void onPageScrollStateChanged(int state) { 
 
       if(MyFragment.mActionMode != null) MyFragment.mActionMode.finish(); 
 
      } 
 

 

 
     });

1

können Sie die onDestroyOptionsMenu() Methode in Ihrem Fragment verwenden:

public void onDestroyOptionsMenu() { 
    super.onDestroyOptionsMenu(); 
    if (mActionMode != null) { 
     mActionMode.finish(); 
     mActionMode = null; 
    } 
} 
Verwandte Themen