contextual action mode in fragment - close if not focused?
Asked Answered
T

5

9

i implemented a contextual action mode bar in a nested fragement. This fragment is part of a view pager and the view pager is also a fragment and part of a navigation drawer.

My Problem: I want to close the contextual action mode bar if the fragment is no more focused. So, if I swipe through the view pager the action mode bar should close. But if I use the onPause() method of the nested fragment, the method is not called directly. Often it waits until i swiped two or three times forward... Here are some pictures:

enter image description here

enter image description here

In the second picture you can see that the action mode bar is still there. So my question is: In which method should I call my actionModeBar.finish() method, to close directly the action mode bar if i leave the fragment?

Maybe the code of the fragment helps you:

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();
      }
  }
}
Turnaround answered 13/8, 2013 at 8:39 Comment(0)
E
7

ViewPagers keep multiple pages active at any one time (by default, the page before and page after the currently shown page), hence why onPause() is not called until you swipe two pages away.

Your best bet would be to use a ViewPager.OnPageChangeListener, and show and hide the ActionMode in onPageSelected(..) (i.e. if the page selected isn't the one with the ActionMode, hide the ActionMode). You'll likely have to implement this in the Activity which hosts your ViewPager.

Ectoderm answered 13/8, 2013 at 9:43 Comment(1)
onPause() do gets called when you swipe right/left. Maybe viewpager was different back then in 2013 :)Stylize
S
7

Here's what worked for me --

  1. Hold a static reference to the action mode 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. Set ViewPager.OnPageChangeListener in MyViewPagerActivity.

 mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            ....

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


        });
Sitdown answered 23/12, 2015 at 3:21 Comment(0)
C
4

This worked for me:

@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);
    }
}
Carlos answered 3/10, 2014 at 15:40 Comment(1)
That dirty HACK and it is dirty is exactly what I needed. Thanks. I had already tried simply calling Finish on the previously stored actionModeIbadan
A
3

I combined code from the OP with the override suggested by user pomber:

  • I save the ActionMode to a class field when the action mode is created.
  • I set the field back to null when the action mode is destroyed.
  • I override setUserVisibleHint in my fragment and call ActionMode#finish() if the fragment isn't visible in the view pager.
  • I also call ActionMode#finish() in the onPause() method of the fragment to close the fragment if the user navigates elsewhere.

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();
    }
}
Assuming answered 7/10, 2015 at 14:18 Comment(0)
C
2

You can use the onDestroyOptionsMenu() method inside your Fragment:

public void onDestroyOptionsMenu() {
    super.onDestroyOptionsMenu();
    if (mActionMode != null) {
        mActionMode.finish();
        mActionMode = null;
    }
}
Covetous answered 28/8, 2017 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.