5

Zaimplementowałem pasek trybu działania kontekstowego w ramce zagnieżdżonej. Fragment ten jest częścią pager widoku, a pager widoku jest fragmentem i częścią szuflady nawigacji.Tryb działania kontekstowego w fragmencie - zamknąć, jeśli nie jest skoncentrowany?

Mój problem: Chcę zamknąć pasek trybu działania kontekstowego, jeśli fragment nie jest już bardziej skupiony. Tak więc, przesuwając palcem po ekranie podglądu, pasek trybu działania powinien się zamknąć. Ale jeśli użyję metody onPause() zagnieżdżonego fragmentu, metoda nie zostanie wywołana bezpośrednio. Często czeka, aż ja swiped dwa lub trzy razy do przodu ... Oto kilka zdjęć:

enter image description here

enter image description here

Na drugim zdjęciu widać, że pasek tryb działania jest nadal. Więc moje pytanie brzmi: W której metodzie powinienem zadzwonić do mojej metody actionModeBar.finish(), aby zamknąć bezpośrednio pasek trybu działania, jeśli zostawiam fragment?

Może kod fragmentu pomaga:

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

Odpowiedz

5

ViewPagers utrzymać wielu stron aktywnych w tym samym czasie (domyślnie strona przed i strona po aktualnie pokazanym stronie), więc dlaczego OnPause() nie jest wywoływana, dopóki nie przesuniesz dwóch stron dalej.

Najlepiej byłoby użyć ViewPager.OnPageChangeListener i pokazać i ukryć tryb działania w onPageSelected(..) (tj. Jeśli wybrana strona nie jest tą z trybem działania, ukryj tryb działania). Prawdopodobnie będziesz musiał to zaimplementować w Aktywności, w której znajduje się Twój ViewPager.

4

Ten pracował dla mnie:

@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

To brudny HACK i jest brudny właśnie potrzebowałem. Dzięki. Próbowałem już po prostu wywołać polecenie Zakończ na poprzednio zapisanym obiekcie actionMode –

3

I połączeniu kod z OP z ręcznym sugerowanej przez pomber użytkownika:

  • ja uratować ActionMode do pola klasy, gdy tworzony jest tryb działania .
  • Ustawiam pole z powrotem na null, gdy tryb działania zostanie zniszczony.
  • Zastępuję setUserVisibleHint w moim fragmencie i wywołuję ActionMode#finish(), jeśli fragment nie jest widoczny w okienku widoku.
  • Również nazywam ActionMode#finish() w metodzie onPause() fragmentu, aby zamknąć fragment, jeśli użytkownik nawiguje gdzie indziej.

Kod:

@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

Oto co pracował dla mnie -

  1. Trzymaj statyczny odniesienie do trybu działania w 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. Ustaw ViewPager.OnPageChangeListener w MyViewPagerActivity.

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
 

 
      .... 
 

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

 

 
     });

1

Można użyć metody onDestroyOptionsMenu() wewnątrz Fragment:

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