javaandroidnavigationback-stackfragment-backstack

Is there an easy way to prevent fragments from going back by using the back button on android


I am trying to figure out an easy solution without overcomplicating things on preventing certain screens in the app from going back when they use the back button of the android device however, I am not sure which approach is best in my situtation.

The application is not using navigation component and its quite a large project already to implement that, there are screens such as the login which if you press the back button after login in, it will take you back to the login. Fortunatly the login screen is an activity so I can just do finish(); after startActivity(i); and that sorts it out however, there are multiple fragments after login in which causes issues such as duplications and re-entering values that you did not mean to by simply pressing the back button.

What I am currently doing is fragmentTransaction.addToBackStack(null); before I do commit(); I tried removing the fragmentTransaction.addToBackStack(null); where I did not wanted it and it kind of worked but it would not take you back to a specific screen when you would use the back button, it will take you to the last fragmentTransaction.addToBackStack(null); used and that is causing confusion in some cases.

Example of what I am usually doing:

  Fragment enqFragment = new EnqFragment();
  //Fragment findCustomerFragment = new AppInformationFragment();
  FragmentTransaction transaction = requireActivity().getSupportFragmentManager().beginTransaction();

  // Replace whatever is in the fragment_container view with this fragment,
  // and add the transaction to the back stack if needed
  transaction.replace(R.id.fragment_container, enquiryFragment);
  transaction.addToBackStack(null); // I would comment this out if I did not want to go back here
  transaction.commit();

What I want to do is go from A to B to C but when I press back I want to go back to A and in some cases when C goes to D and back is pressed I want to again go to A or B depends on the occasion. Is Navigation components the most ideal way to go with this or is there an easier solution to achieve this and what are the pros and cons?


Solution

  • Well first you need to keep in mind that when the user pressed the back button or when onBackPressed is called, the default behaviour is popping off the latest fragment from the stack. You can customise this behaviour as follows as it is easier than going and overriding onBackPressed in each case

    Using the navigation component which was introduced in Jetpack

    SOLUTION 1:

    The app:popUpTo and app:popUpToInclusive are exactly what you may be looking for

    Via the documentation,the xml attributes will

    Pop up to a given destination before navigating. This pops all non-matching destinations from the back stack until this destination is found

    Let me explain this to you with three fragments A , B, C

    A (start) -> B -> C
       
    

    if I want to navigate to C and pop all including A(startscreen) then the code will be:

     <action
                android:id="@+id/B_to_C"
                app:destination="@id/C"
    
                app:popUpTo="@+id/A"
                app:popUpToInclusive="true" />
    

    if I want to navigate to C and pop all excluding A then the code will be:

      <action
                android:id="@+id/action_B_to_C"
                app:destination="@id/C"
    
                app:popUpTo="@+id/A"/>
    

    SOLUTION 2:

    Using the popBackStack method of the NavController class which does the same job as the onBackPressed but in an elegant way

    If you have three fragments : A, B, C

    And you are currently in fragment C and would like to go back to A before navigating anywhere(or not navigating anywhere if you please)

    NavController controller = Navigation.findNavController(view);
    controller.popBackStack(R.id.fragmentB, true);
    

    OR

    NavController controller = Navigation.findNavController(view);
    controller.popBackStack(R.id.fragmentA, false);
    

    where true or false will indicate if you actually want the destination to stay(false) or be popped off the stack too (true)

    Using the same without navigation component i.e. older FragmentManager class

    The example above nicely explains the behaviour, however you can use methods like popBackStack, and its variations