5

How do we track bottom menu nav items clicks only when bottom menu items are clicked and still use setupWithNavController ? Currently using Bottom navigation view 2.4.0-alpha05, we have a use case for tracking bottom nav clicks for analytics and bottom nav is set like below

binding.bottomNavigationView.setupWithNavController(navController)

If I use below, then bottom nav selection stops working.

binding.bottomNavigationView.setOnItemSelectedListener { 
        //track clicks
        true
    } 

An Alternative to this to copy the source code NavigationUi.setupWithNavController and alter it like below however I'm not sure if this has repercussions, say for example if google adds improvement or changes setupWithNavController later, then the project will miss that change :

    private fun setupWithNavController(
        navigationBarView: NavigationBarView,
        navController: NavController,
        onItemSelected: ((Int) -> Unit)
    ) {
        navigationBarView.setOnItemSelectedListener { item ->
            onItemSelected.invoke(item.itemId)
            NavigationUI.onNavDestinationSelected(
                item,
                navController
            )
        }
        val weakReference = WeakReference(navigationBarView)
        navController.addOnDestinationChangedListener(
            object : NavController.OnDestinationChangedListener {
                override fun onDestinationChanged(
                    controller: NavController,
                    destination: NavDestination,
                    arguments: Bundle?
                ) {
                    val view = weakReference.get()
                    if (view == null) {
                        navController.removeOnDestinationChangedListener(this)
                        return
                    }
                    view.menu.forEach { item ->
                        if (destination.matchDestination(item.itemId)) {
                            item.isChecked = true
                        }
                    }
                }
            })
    }
Vyshakh Amarnath
  • 636
  • 6
  • 17
  • Can you add a listener for navigation events instead? – Henry Twist Aug 03 '21 at 12:01
  • I tried adding onClickListener but that doesnt work if thats what you mean.. – Vyshakh Amarnath Aug 03 '21 at 15:54
  • 2
    No. I meant this: [How to listen to Fragment Change in Navigation Component?](https://stackoverflow.com/questions/56284403/how-to-listen-to-fragment-change-in-navigation-component) – Henry Twist Aug 03 '21 at 23:28
  • Thanks @HenryTwist, works like a charm! for setOnItemSelectedListener to break the navigation functionality is that a bug? sounds like a bug to me – Bruce Mar 29 '22 at 00:11
  • I don't think I would call it a bug @Bruce. The navigation components are built to interface with existing views, I doubt there would be another way around taking control of the listeners (without reflection). Maybe a limitation imposed by the framework, but not a bug as such. – Henry Twist Mar 29 '22 at 09:24

1 Answers1

8

You can get MenuItem from your BottomNavigationView:

bottomNavigationView?.menu?.findItem(R.id.your_menu_item_id) // by menu item id

or

bottomNavigationView?.menu?.get(index) // by index

After you got MenuItem you can subscribe to click on MenuItem:

bottomNavigationView?.menu?.findItem(R.id.your_menu_item_id)?.setOnMenuItemClickListener {
    // TODO: add your code
    return@setOnMenuItemClickListener false
}

NavigationComponent works well and you are able to handle clicks on BottomNavigationView items.

Fr2eman
  • 156
  • 2
  • 7