Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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..

like image 274
Android Developer Avatar asked Nov 01 '14 08:11

Android Developer


People also ask

How do you complete a fragment in navigation component?

How do I get rid of current fragment navigation component? You add to the back state from the FragmentTransaction and remove from the backstack using FragmentManager pop methods: FragmentManager manager = getActivity(). getSupportFragmentManager();

How do you close a back pressed app on Android?

In order to check when the 'BACK' button is pressed, use onBackPressed() method from the Android library. Next, perform a check to see if the 'BACK' button is pressed again within 2 seconds and will close the app if it is so. Otherwise, don't exit.

How do you adding removing and replacing fragments?

Use replace() to replace an existing fragment in a container with an instance of a new fragment class that you provide. Calling replace() is equivalent to calling remove() with a fragment in a container and adding a new fragment to that same container. transaction. commit();


2 Answers

This is how I solved it..When you press back button inside your fragment onBackPressed() method of your activity will be called if you have declared that..So handling back button for fragments within navigation drawer can be one in this way..

MainActvity

     public static boolean isMainActivityShown ;
     public static boolean isFragment1Shown=false ;
     public static boolean isFragment2Shown=false ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        isMainActivityShown=true  //inside onCreate method put isMainActivityShown true
        . 
        . 
        .
        {
        Fragment currentFragment = new Fragment1();
        isMainActivityShown=false;   //when moving to fragment1 
        isFragment1Shown=true;
        frgManager = getFragmentManager();
        frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
                                        .commit();
        }
        .
        .
        }
     @Override
        public void onBackPressed() {

            if(isMainActivityShown)
            {
                finish();
            }
            else if(isFragment1Shown)
            {
               //write the code to handle back button when you are in Fragment1
            }
           else if(isFragment2Shown)
            {  //When you are in Fragment 2 pressing back button will move to fragment1
                Fragment currentFragment = new Fragment1();
                isFragment2Shown=false;
                isFragment1Shown=true;

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

            }

Fragment1

Fragment currentFragment = new Fragment2();
MainActivity.isFragment1Shown=false;
MainActivity.isFragment2Shown=true;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
                                    .commit();
like image 124
Android Developer Avatar answered Oct 13 '22 03:10

Android Developer


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.

like image 25
Phantômaxx Avatar answered Oct 13 '22 02:10

Phantômaxx