contextual action mode in fragment - close if not focused?

筅森魡賤 提交于 2019-12-04 09:31:11

问题


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:

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

回答1:


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.




回答2:


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


        });



回答3:


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



回答4:


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



回答5:


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

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


来源:https://stackoverflow.com/questions/18204386/contextual-action-mode-in-fragment-close-if-not-focused

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!