3

In my application i am using Jetpack Navigation with BottomNavigationView. I have like 4 fragments:Home,Search,Notifications,Profile and when i am in Home fragment, i click again home item in bottom navigation view, it re-creates the fragment. I searched, but mainly answers were for those who did not use jetpack navigation.

(by the way, i only want fragment not being re-created when i am on that fragment already, if i am not in that fragment, it is okay to be re-created)

Below is my setup:

val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView_mainActivity) as NavHostFragment
navController = navHostFragment.navController 
binding.bottomNavView.setupWithNavController(navController)

And this is the gif image that shows how bottom navigation view does behave

nasibeyyubov
  • 1,735
  • 3
  • 11
  • 28

5 Answers5

0

I read the source code of Google. I saw that, It always creates new fragment.

You have a bottom navigation like the app that I'm building. :))

enter image description here

For me, I didn't use menu item for bottom navigation view. I added a custom view for it.

(I have MainActivity, MainViewModel for managing the action bar, bottom navigation view .)

And then in custom view, when the customer click on item, I will check the page that they want to open is the same with the current page or not. If they are the same, I will not open it. Like this:

fun openHomePage() {
        if (pageID.value != R.id.nav_home) {
            pageID.postValue(R.id.nav_home)
        }
    }

pageID stores the id of current page:

 var pageID = MutableLiveData<Int>()
        private set

In MainActivity:

mainViewModel.pageID.observe(this, Observer {
            val currentPageId = findNavController(R.id.nav_host_fragment).currentDestination?.id
            if (it != 0 && it != currentPageId) {
                drawerLayout.close()
                navigatePageWithId(it)
            }
        })
NhatVM
  • 1,964
  • 17
  • 25
0

This is a bug that has been around for a while and Google has not provided the official way to deal with it. More info is that because there is only one stack that swap in and out the fragment, you can read more from the SO's post

Android JetPack navigation with multiple stack

But you're using kotlin, you can refer this Github's repo where they provided a workaround for this situation

Dennis Nguyen
  • 278
  • 2
  • 9
0

I ended up using code below.(Considering there is not best solution, it works for me as i want) currentFragmentIndex is the integer value declared in above scope which shows the fragment we are currently in.

binding.bottomNavView.setOnNavigationItemSelectedListener {
            when (it.itemId) {
                R.id.homeFragment -> {
                    if (currentFragmentIndex == 0) {
                        false
                    } else {
                        currentFragmentIndex = 0
                        navController.navigate(R.id.homeFragment)
                        true
                    }
                }
                R.id.searchFragment -> {
                    if (currentFragmentIndex == 1) {
                        false
                    } else {
                        currentFragmentIndex = 1
                        navController.navigate(R.id.searchFragment)
                        true
                    }
                }
                R.id.notificationsFragment -> {
                    if (currentFragmentIndex == 2) {
                        false
                    } else {
                        currentFragmentIndex = 2
                        navController.navigate(R.id.notificationsFragment)
                        true
                    }
                }
                R.id.myProfileFragment -> {
                    if (currentFragmentIndex == 3) {
                        false
                    } else {
                        currentFragmentIndex = 3
                        navController.navigate(R.id.myProfileFragment)
                        true
                    }
                }
                else -> false
            }

        }
nasibeyyubov
  • 1,735
  • 3
  • 11
  • 28
0

This is the right way to prevent fragments from recreation while using bottom navigation via Jetpack Navigation

 binding.bottomNavView.setOnNavigationItemReselectedListener {
        // Do nothing to ignore the reselection
    }
Asad Mahmood
  • 532
  • 1
  • 5
  • 15
  • Despite the fact this is already deprecated (`setOnItemReselectedListener`), this only solves the issue for reselection when current fragment is selected. Actually, you should use `setOnItemSelectedListener` and do proper navigation logic there. However it still solves issue only for clicking bottom nav item for fragment that is currently visible. – M. Wojcik Oct 07 '21 at 10:53
  • @M.Wojcik please have a look at https://stackoverflow.com/a/58210550/11972666 – Asad Mahmood Oct 07 '21 at 12:35
0

If current item id same as last id then return false value. otherwise call your fragment which you have select

bottomNavigation.setOnItemSelectedListener { item ->
if (item.itemId == bottomNavigation.selectedItemId) {
    false
} else {
    when (item.itemId) {
        R.id.home -> {
            //replaceFragment
        }
        R.id.chats -> {
            //replaceFragment
        }
        R.id.setting -> {
            //replaceFragment
        }
    }
    true
 }

}
Kishan Viramgama
  • 893
  • 1
  • 11
  • 23