contextual action mode in fragment - close if not focused?

佐手、 提交于 2019-12-03 07:55:23

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.

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


        });

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

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

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

public void onDestroyOptionsMenu() {
    super.onDestroyOptionsMenu();
    if (mActionMode != null) {
        mActionMode.finish();
        mActionMode = null;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!