Search code examples
androidandroid-fragmentsback-button

App exits on presing back button inside fragments within navigation drawer


My app exits when i try to move from child fragment to parent fragment(it doesn't crashes).Here LandingActivity.java is main activity in which I am calling fragment ChannelGrid.java which calls fragment GridMain.java.When i presses back button of mobile in fragment GridMain app exits rather than moving to ChannelGrid.java.I have added addToBackStack("tag") to fragments and also tried using onKey()..I tested my app on different devices also..I checked out other solutions with same issue and tried them but nothing works..

Navigation Drawer-LandingActivity.java-ChaanelGrid.java(Fragment)-GridMain.java(Fragment)

LandingActivity.java

   currentFragment = new ChaanelGrid();

                currentFragment.setArguments(args);
                frgManager = getFragmentManager();

                frgManager.beginTransaction().add(R.id.content_frame, currentFragment).addToBackStack("tag")
                        .commit();

ChaanelGrid.java

Fragment currentFragment = new GridMain();



                    FragmentManager frgManager;
                    frgManager = getFragmentManager();
                    frgManager.beginTransaction().add(R.id.content_frame, currentFragment).addToBackStack("GridMain")
                            .commit()

GridMain.java(i tried without onKey() method also but didn't worked)

rootView.setOnKeyListener(new View.OnKeyListener() {


   @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK)
            {
                Fragment currentFragment = new ChaanelGrid();


                FragmentManager frgManager;
                frgManager = getFragmentManager();
                frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
                        .commit();
                return true;
            }

logcat verbose

   10-31 21:46:57.954  24452-24452/D/ActivityThread﹕ ACT-AM_ON_PAUSE_CALLED ActivityRecord{41eb8b98 token=android.os.BinderProxy@41bb9828 {xyz/xyz..activity.LandingActivity_}}
10-31 21:46:57.971  24452-24452/ D/ActivityThread﹕ ACT-PAUSE_ACTIVITY_FINISHING handled : 0 / android.os.BinderProxy@41bb9828
10-31 21:46:58.007  24452-24452/ V/InputMethodManager﹕ focusOut: android.widget.GridView@41f06f40 mServedView=android.widget.GridView@41f06f40 winFocus=false
10-31 21:46:58.297  24452-24452/ I/SurfaceTextureClient﹕ [0x5143bc58] frames:44, duration:1.002000, fps:43.883736
10-31 21:46:58.350  24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.432  24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.753  24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.754  24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.755  24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 2)
10-31 21:46:58.879  24452-24452/ D/ActivityThread﹕ ACT-DESTROY_ACTIVITY handled : 1 / android.os.BinderProxy@41bb9828

I tried adding following in LandingActivity.java

@Override

public void onBackPressed() {
    FragmentManager frgManager;
    frgManager = getFragmentManager();

    Fragment fragment = fragmentManager.findFragmentByTag("GridMain");
    if (fragment != null) {
        GridMain gridMain = (GridMain) fragment;
        if (!gridMain.onBackPressed()) {
            super.onBackPressed();
        }
    }
    else {
        super.onBackPressed();
    }
}

and following in GridMain.java

   protected boolean onBackPressed() {
        FragmentManager frgManager;
        frgManager = getFragmentManager();
        frgManager.popBackStack();
        return true;
    }

Using Log i checked tht onBackPressed() of LandingActivity.java is being called but still the same output..


Solution

  • This is how I normally handle the Back Button:

    // "State Machine" variables: to indicate which is the active Fragment.
    private static boolean isHelpShown = false;
    protected static boolean isInfoShown = false;
    protected static boolean isMainShown = false;
    private static boolean isViewShown = false;
    
    // Used to switch between Fragments.
    private static enum Fragments
    {
        MAIN,
        VIEW,
        HELP,
        INFO
    }
    
    @Override
    public final void onBackPressed()
    {
        if (isMainShown)
        {
            // We're in the MAIN Fragment.
            finish();
        }
        else
        {
            // We're somewhere else, reload the MAIN Fragment.
            showFragment(Fragments.MAIN);
        }
    }
    
    private final void showFragment(final Fragments FragmentType)
    {
        isViewShown = false;
        isHelpShown = false;
        isInfoShown = false;
        isMainShown = false;
    
        final FragmentTransaction ft =
            getSupportFragmentManager().beginTransaction();
    
        /*
        Replace whatever is in the fragment_container view with this
        fragment, and add the transaction to the back stack so the user can
        navigate back.
        */
        switch(FragmentType)
        {
            case HELP:
            {
                ft.replace(R.id.frgMaster, new FRG_Help());
                isHelpShown = true;
                break;
            }
            case INFO:
            {
                ft.replace(R.id.frgMaster, new FRG_Info());
                isInfoShown = true;
                break;
            }
            case VIEW:
            {
                ft.replace(R.id.frgMaster, new FRG_View());
                isViewShown = true;
                break;
            }
            case MAIN:
            {
                ft.replace(R.id.frgMaster, new FRG_Main());
                isMainShown = true;
                break;
            }
        }
    
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    
        // Finalize the transaction...
        ft.commit();
    
        getSupportFragmentManager().executePendingTransactions();
    }
    

    As you can see, for my needs I only handle when we're in the MAIN Fragment (I quit) or when we aren't (I go back to the MAIN Fragment: another Back press and it quits).

    You can add more checks in the onBackPressed method to check if you are in another Fragment and load another one, accordingly.