contextual action mode in fragment - close if not focused?

前端 未结 5 776
小蘑菇
小蘑菇 2021-02-04 15:08

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.

相关标签:
5条回答
  • 2021-02-04 15:46

    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();
        }
    }
    
    0 讨论(0)
  • 2021-02-04 15:59

    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.

    0 讨论(0)
  • 2021-02-04 16:01

    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);
        }
    }
    
    0 讨论(0)
  • 2021-02-04 16:05

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

    0 讨论(0)
  • 2021-02-04 16:09

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

    public void onDestroyOptionsMenu() {
        super.onDestroyOptionsMenu();
        if (mActionMode != null) {
            mActionMode.finish();
            mActionMode = null;
        }
    }
    
    0 讨论(0)
提交回复
热议问题