Android Jetpack Navigation, BottomNavigationView with Youtube or Instagram like proper back navigation (fragment back stack)?

前端 未结 13 1880
误落风尘
误落风尘 2020-12-12 10:25

Android Jetpack Navigation, BottomNavigationView with auto fragment back stack on back button click?

What I wanted, after choosing multiple tabs one after another by

相关标签:
13条回答
  • 2020-12-12 11:04

    The best solution is the solution that is provided by google team on his repo, the back button still sends u back to first button but the rest behavior its "normal"... It looks strage that Google is still not provinding a good solution, even when they are using it on (youtube, Google Photos, etc), they said androidx its out there to help, but is look like just we go around and find a workaround for the normal stuff.

    Here is the link to google Repo where they are using nav. bottom with a navGraph per each button. https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt copy this file into ur project and have a look how it`s implemented in their project. For back button behavior u can create un own stack and onBackpressed just navigate on that stack.

    0 讨论(0)
  • 2020-12-12 11:04

    Originally answered here: https://stackoverflow.com/a/63645978/8956093

    In Jetpack Navigation Componenet, if you want to perform some operation when fragment is poped then you need to override following functions.

    1. Add OnBackPressedCallback in fragment to run your special operation when back is pressed present in system navigation bar at bottom.

       override fun onCreate(savedInstanceState: Bundle?) {
           super.onCreate(savedInstanceState)
      
           onBackPressedCallback = object : OnBackPressedCallback(true) {
               override fun handleOnBackPressed() {
                   //perform your operation and call navigateUp
                  findNavController().navigateUp()
               }
           }
       requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
       }
      
    2. Add onOptionsItemMenu in fragment to handle back arrow press present at top left corner within the app.

       override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
           super.onViewCreated(view, savedInstanceState)
      
           setHasOptionsMenu(true)
       }
      
      override fun onOptionsItemSelected(item: MenuItem): Boolean {
         if (item.itemId == android.R.id.home) {
             //perform your operation and call navigateUp
             findNavController().navigateUp()
             return true
         }
         return super.onOptionsItemSelected(item)
      }
      
    3. If there is no special code to be run when back is pressed on host fragment then use onSupportNavigateUp in Activity.

       override fun onSupportNavigateUp(): Boolean {
         if (navController.navigateUp() == false){
           //navigateUp() returns false if there are no more fragments to pop
           onBackPressed()
         }
         return navController.navigateUp()
       }
      

    Note that onSupportNavigateUp() is not called if the fragment contains onOptionsItemSelected()

    0 讨论(0)
  • 2020-12-12 11:05

    In the jetpack navigation, you have to make changes in only single navigation graph xml file for handle navigation, handle backstacks, custom animations, pass arguments between fragments.

    If you want simply back to previous fragment,

    <action
            android:id="@+id/action_deleteEmployeeFragment_to_employeesListFragment2"
            app:destination="@id/employeesListFragment"/>
    
    
        btn_cancel.setOnClickListener {
                    it.findNavController().popBackStack()
                }
    

    If you want to clear all backstacks and go to new fragment

    <action
            android:id="@+id/action_deleteEmployeeFragment_to_employeesListFragment2"
            app:destination="@id/employeesListFragment"
            app:popUpTo="@id/employeesListFragment"
            app:popUpToInclusive="true"
            app:launchSingleTop="true" />
    
    
     btn_submit.setOnClickListener {
                       it.findNavController().navigate(DeleteEmployeeFragmentDirections.actionDeleteEmployeeFragmentToEmployeesListFragment2())
            }
    

    For more reference: Jetpack Navigation Example

    0 讨论(0)
  • 2020-12-12 11:11

    I have made an app like this (still not published on PlayStore) that has the same navigation, maybe its implementation is different from what Google does in their apps, but the functionality is the same.

    the structure involves I have Main Activity that I switch the content of it by showing/hiding fragments using:

    public void switchTo(final Fragment fragment, final String tag /*Each fragment should have a different Tag*/) {
    
    // We compare if the current stack is the current fragment we try to show
    if (fragment == getSupportFragmentManager().getPrimaryNavigationFragment()) {
      return;
    }
    
    // We need to hide the current showing fragment (primary fragment)
    final Fragment currentShowingFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
    
    final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    if (currentShowingFragment != null) {
      fragmentTransaction.hide(currentShowingFragment);
    }
    
    // We try to find that fragment if it was already added before
    final Fragment alreadyAddedFragment = getSupportFragmentManager().findFragmentByTag(tag);
    if (alreadyAddedFragment != null) {
      // Since its already added before we just set it as primary navigation and show it again
      fragmentTransaction.setPrimaryNavigationFragment(alreadyAddedFragment);
      fragmentTransaction.show(alreadyAddedFragment);
    } else {
      // We add the new fragment and then show it
      fragmentTransaction.add(containerId, fragment, tag);
      fragmentTransaction.show(fragment);
      // We set it as the primary navigation to support back stack and back navigation
      fragmentTransaction.setPrimaryNavigationFragment(fragment);
    }
    
    fragmentTransaction.commit();
    }
    
    0 讨论(0)
  • 2020-12-12 11:11

    Short and good code in Kotlin to connect bottom navigation items with fragments inside navigation graph:

        val navControl = findNavController( R.id.nav_host_frag_main)
        bottomNavigationView?.setupWithNavController(navControl)
    

    *Just consider:Bottom navigation id's & fragments inside navigation graph must have the same id. Also thanks to good explanation from @sanat Answer

    0 讨论(0)
  • 2020-12-12 11:12

    You can have a viewpager setup with bottom navigation view. Each fragment in the viewpager will be a container fragment, it will have child fragments with its own backstack. You can maintain backstack for each tab in viewpager this way

    0 讨论(0)
提交回复
热议问题