BottomNavigation State gets lost after opening browser and then navigating back

Issue

Today, I discovered a very weird bug in my app. It goes the following: When the user navigates to the “profile screen”, then opens the “information screen” and after that clicks on “agb”, my app opens a browser and navigates the user to my website. Now the weird thing: When the user navigates back (to the “information screen”, the bottomnavigation indicates, that he is currently on the home tab. Navigating back again (to the “profile screen”), then solves this issue. So it goes:

“Profile Screen” -> “Information Screen” -> Clicking on link -> “Opening Browser” -> Clicking Back -> State gets lost -> “Information Screen” -> Clicking Back -> State gets restored -> “Profile Screen”.

I added some pictures that show the error (red indicates the state, blue a action)

  1. Profile Screen (correct state)
  2. Information Screen (correct state)
  3. Browser (Probably state destroyed now)
  4. Information Screen (state destroyed)
  5. Profile Screen (state restored)

Fragment (Information Screen)

class UserInformationFragment : Fragment(R.layout.fragment_user_information) {
    private var _binding: FragmentUserInformationBinding?  null
    private val binding: FragmentUserInformationBinding get()  _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding    FragmentUserInformationBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initUserToolbar()

        with(binding) {
            agbCv.setOnClickListener { startBrowser(INTERNET_AGB) }
            dataProtectionCv.setOnClickListener { startBrowser(INTERNET_DATA_PROTECTION) }
            impressumCv.setOnClickListener { startBrowser(INTERNET_IMPRESSUM) }
        }

    }

    private fun startBrowser(url: String) {
        val browserIntent  Intent(Intent.ACTION_VIEW, Uri.parse(url))
        startActivity(browserIntent)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding  null
    }
}

One Idea I had was to set the state manually to the profile screen again after the user navigates back. But that would be a real mess and weird to do..

navigation_version  2.3.5

implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"

Solution

Okay, I’ve managed to solve this problem. The problem had nothing to do with opening the browser, but with the recreation of my activity and reinflating of my bottomnavigation#menu. Before I had this:

private fun setUpBottomNav(newMenu: Int) {
    with(binding.bottomNavigationView) {
        menu.clear()
        inflateMenu(newMenu)
        setupWithNavController(findNavController(R.id.fragment_container))
        // fix blinking when re selecting bottom nav item
        setOnItemReselectedListener {}
    }
}

The problem was that setUpBottomNav() was called, after getting back from the browser to my app, because the activity was recreated. The new solution is this:

private fun setUpBottomProfile(newMenu: Int) {
    val controller  (supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment).navController

    with(binding.bottomNavigationView) {
        val currentSelectedItem  selectedItemId

        menu.clear()
        inflateMenu(newMenu)

        selectedItemId  currentSelectedItem

        setupWithNavController(controller)
        // fix blinking when re selecting bottom nav item
        setOnItemReselectedListener {}
    }
}

Answered By – Andrew

Leave a Comment