Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Changing menu item visibility in a destination

Using androidx navigation framework, I am able to switch between navigation fragment destinations (both using menu and other in-fragment actions). Now, I need to show a share button when I am in a given destination, and hide it in all the others.

I managed to do this, but I need to invoke invalidateOptionsMenu() each time a destination is changed. Is this the right way or are there any more elegant ways?

MainActivity

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class MainActivity : AppCompatActivity() {
    private var isGivenDestination = false
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        navHostFragment.navController.addOnDestinationChangedListener {_, destination, _ ->
            invalidateOptionsMenu()
            isGivenDestination = destination.id == R.id.given_destination
        }
    }
    override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
        val result = super.onPrepareOptionsMenu(menu)
        menu?.findItem(R.id.nav_share)?.let {
            if (it.isVisible != isGivenDestination) {
                it.isVisible = isGivenDestination
            }
        }
        return result
    }
}

>Solution :

Your approach to showing and hiding the share button based on the current navigation destination is fundamentally correct. Using invalidateOptionsMenu() in conjunction with onPrepareOptionsMenu() is a standard way to dynamically change menu items.

However, if you’re looking for a more elegant solution, you might consider the following approaches:

  1. Using LiveData: If you’re already using a ViewModel with LiveData in your app, you can tie the visibility of the share button to a LiveData object that represents the current destination.

In your ViewModel:

val isShareVisible: MutableLiveData<Boolean> = MutableLiveData(false)

In your MainActivity:

class MainActivity : AppCompatActivity() {
    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        navHostFragment.navController.addOnDestinationChangedListener { _, destination, _ ->
            viewModel.isShareVisible.value = destination.id == R.id.given_destination
        }

        viewModel.isShareVisible.observe(this, Observer { isVisible ->
            invalidateOptionsMenu()
        })
    }

    override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
        val result = super.onPrepareOptionsMenu(menu)
        menu?.findItem(R.id.nav_share)?.isVisible = viewModel.isShareVisible.value ?: false
        return result
    }
}
  1. Directly Modifying the Menu Item
    If the change you need to make to the menu is relatively simple and isolated, like just showing or hiding a single item, you can directly modify the visibility of the menu item within the addOnDestinationChangedListener.

In your MainActivity:

class MainActivity : AppCompatActivity() {
    ...
    private var shareMenuItem: MenuItem? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        navHostFragment.navController.addOnDestinationChangedListener { _, destination, _ ->
            shareMenuItem?.isVisible = destination.id == R.id.given_destination
        }
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.your_menu, menu)
        shareMenuItem = menu?.findItem(R.id.nav_share)
        return true
    }
}

Both of these approaches have their own advantages. The LiveData approach integrates well with a ViewModel-based architecture and keeps your UI logic more declaratively structured.

The direct modification approach is simpler and more straightforward but might be less scalable if you have multiple conditions or more complex UI logic to handle.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading