Android : Return to previous fragment on back press

前端 未结 5 1363
南笙
南笙 2021-02-12 17:44

I have implemented Navigation Drawer which is a subclass of Activity. I have many fragments in my application. My question goes here

Imagine there are 3 fragments :

相关标签:
5条回答
  • 2021-02-12 18:25

    Use this code on tab change in your main activity to clear the stack.

    int count = getFragmentManager().getBackStackEntryCount();
            if(count>0){
                for (int i = 0; i <count; i++) {
                    getFragmentManager().popBackStack();
                }
            }
    

    Then on Back pressed of your main activity do this

     int count = getFragmentManager().getBackStackEntryCount();
    
         if (count == 0) {
             super.onbackpressed();
            }
    else {
            getFragmentManager().popBackStack();
        }
     }
    
    0 讨论(0)
  • 2021-02-12 18:27

    You have to implement your own backstack implementation as explained here

    Separate Back Stack for each tab in Android using Fragments

    You can call the popFragments() whenever you click the back button in a fragment and call pushFragments() whenever you navigate from one Fragment to other.

    in Short,

    public void onBackPressed()
    {
        FragmentManager fm = getActivity().getSupportFragmentManager();
        fm.popBackStack();
    }
    
    0 讨论(0)
  • 2021-02-12 18:36

    Update your Activity#onBackPressed() method to:

    @Override
    public void onBackPressed() {
        if (getFragmentManager().getBackStackEntryCount() > 0) {
            getFragmentManager().popBackStack();
        } else {
            super.onBackPressed();
        }
    }
    

    The reason your implementation doesn't work is because the method FragmentManager#popBackStack() is asynchronous and does not happen right after it is called.

    From the documentation:

    This function is asynchronous -- it enqueues the request to pop, but the action will not be performed until the application returns to its event loop.

    Reference: http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack(java.lang.String,%20int)

    0 讨论(0)
  • 2021-02-12 18:36

    Here is working and tested code by me, This will help you

     private static final int TIME_INTERVAL = 2000;
    private long mBackPressed;
     private void applyExit() {
        if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
            finish();
        } else {
             Toast.makeText(this,"Press Again to exit",Toast.LENGTH_LONG).show();
        }
        mBackPressed = System.currentTimeMillis();
    }
    
    @Override
    public void onBackPressed() {
        fm = getSupportFragmentManager();
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        }
        if (fm.getFragments().size() <= 1) {
            applyExit();
        } else {
            for (Fragment frag : fm.getFragments()) {
                if (frag == null) {
                    applyExit();
                    return;
                }
                if (frag.isVisible()) {
                    FragmentManager childFm = frag.getChildFragmentManager();
                    if (childFm.getFragments() == null) {
                        super.onBackPressed();
                        return;
                    }
                    if (childFm.getBackStackEntryCount() > 0) {
                        childFm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                        return;
                    } else {
                        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                        return;
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-12 18:37

    The tric is in FragmentManager#executePendingTransactions();.

    This is what I use for nested fragments as well...:

    /**
     * if there is a fragment and the back stack of this fragment is not empty,
     * then emulate 'onBackPressed' behaviour, because in default, it is not working.
     *
     * @param fm the fragment manager to which we will try to dispatch the back pressed event.
     * @return {@code true} if the onBackPressed event was consumed by a child fragment, otherwise
     */
    public static boolean dispatchOnBackPressedToFragments(FragmentManager fm) {
    
        List<Fragment> fragments = fm.getFragments();
        boolean result;
        if (fragments != null && !fragments.isEmpty()) {
            for (Fragment frag : fragments) {
                if (frag != null && frag.isAdded() && frag.getChildFragmentManager() != null) {
                    // go to the next level of child fragments.
                    result = dispatchOnBackPressedToFragments(frag.getChildFragmentManager());
                    if (result) return true;
                }
            }
        }
    
        // if the back stack is not empty then we pop the last transaction.
        if (fm.getBackStackEntryCount() > 0) {
            fm.popBackStack();
            fm.executePendingTransactions();
            return true;
        }
    
        return false;
    }
    

    and in my onBackPressed :

                    if (!FragmentUtils.dispatchOnBackPressedToFragments(fm)) {
                        // if no child fragment consumed the onBackPressed event,
                        // we execute the default behaviour.
                        super.onBackPressed();
                    }
    
    0 讨论(0)
提交回复
热议问题