OptionsMenu in nested fragments with Nav component - android

I'm using Navigation Architecture Component
and nested fragments (only 1 activity in my app and shared ToolBar). In fragment A I do:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.scan_menu, menu)
}
Then I show a new fragment B using something like this:
findNavController().navigate(R.id.action_a_b)
The navigation part of it works fine, but the menu created in fragment A sticks around when fragment b is shown (actually, it is never cleared). Isn't this supported in the nav arch components? How am I supposed to attack this? I do not wan't to perform hacks by clearing the menu manually in literally all other fragment due to one of them adding a menu.
Thanks!

Since there doesn't seem to be any solution, I ended up with keeping a reference to the MenuItem, and hide/show:
private var menuItem: MenuItem? = null
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.scan_menu, menu)
menuItem = menu.findItem(R.id.scan_menu_manual)
}
override fun onResume() {
super.onResume()
menuItem?.isVisible = true
}
override fun onPause() {
super.onPause()
menuItem?.isVisible = false
}
That seems to work for now.

Related

I can't work MenuProvider in Fragment for menu

class FirstFragment : Fragment(), MenuProvider {
...
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
//not called
menuInflater.inflate(R.menu.menu_, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return true
}
}
<com.google.android.material.navigation.NavigationView
android:id="#+id/nv"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/menu_"/>
I'm trying to add a menu to the fragment (not the action bar), even if I add it in XML,
I can't access it in the code. I tried many ways on the internet, I added menuhost to oncreate,
I updated the version of the modules, but it didn't work, what do I need to know?
I also tried this code,i don't get error but function is not called
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val menuHost: MenuHost = requireActivity() as MenuHost
menuHost.addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
//not called
menuInflater.inflate(R.menu.menu_, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
I solved I saw this code to video:
activity?.addMenuProvider(this)
I added in OnViewCreaded, it's worked

How to add items to the menu bar using the new MenuProvider?

Very much a beginner question here. Since the old paradigm which used "setHasOptionsMenu(true)" in the fragments was recently deprecated in Android Studio, I have been trying to convert my app to the newest scheme as outlined in the documentation. All explanation about this I can find centers around the following code snippet from said documentation:
/**
* Using the addMenuProvider() API directly in your Activity
**/
class ExampleActivity : ComponentActivity(R.layout.activity_example) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Add menu items without overriding methods in the Activity
addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
})
}
}
/**
* Using the addMenuProvider() API in a Fragment
**/
class ExampleFragment : Fragment(R.layout.fragment_example) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// The usage of an interface lets you inject your own implementation
val menuHost: MenuHost = requireActivity()
// Add menu items without using the Fragment Menu APIs
// Note how we can tie the MenuProvider to the viewLifecycleOwner
// and an optional Lifecycle.State (here, RESUMED) to indicate when
// the menu should be visible
menuHost.addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
}
Now, I have tried to add this code to my main activity (extending AppCompatActivity() ) and associated fragments. Wherever it says "R.menu.example_menu" I have inserted my own menu layout files which contain basically only a single settings item most of the time.
However, while the code compiles without error, no item is actually added to the menu bar. What am I missing? Am I supposed to add the items manually where it says "add menu items here"? However, writing something such as "menu.add("Settings") doesn't seem to have an effect either.
Try the following in the Main Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_example)
In other words, use AppCompatActivity() instead of ComponentActivity(), because AppCompatActivity() extends FragmentActivity which extends ComponentActivity().
make sure to use the androidX dependencies (import androidx.appcompat.app.AppCompatActivity)
Also, I am not sure what items you have, but it could be because of their constraints in the xml files.
For example, if you have a TextView and you used
tools:text="toolsText, you won't be able to see the text, since this is used only for Android Studio layout preview and it doesn't show text when you run the app.
I hope this can be helpful for you.

How to update option menu item icon?

Here is my code I want to update menu item icon based on data I requesting in server that is why I need to have access to menu item in onViewCreated as I think solution which I am doing now is not right as observing data in onPrepareOptionsMenu?
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.menu_favorite, menu)
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
viewModel.favorite
.observe(viewLifecycleOwner, Observer {
if (it.data != null) {
menu.findItem(R.id.action_favorite)?.icon = true
}
})
}

setSupportActionBar inside of a Fragment

I have a Fragment:
class HomeFragment : Fragment() { ... }
Now I'm trying to add an Actionbar to it, but this doesn't work:
setSupportActionBar(findViewById(R.id.toolbar_main))
How can I set the Support and then add Items to the ActionBar?
This is how it works in an AppCompatActivity:
// This adds items to the ActionBar
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_toolbar_main, menu)
return true
}
// This is the OnClickListener for the Buttons in the ActionBar
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.toolbar_edit -> {
true
}
R.id.toolbar_search -> {
true
}
else -> {
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
super.onOptionsItemSelected(item)
}
}
Big thanks in advance!
Override onCreateOptionsMenu in your Fragment and inflate your menu inside. Than in onCreate method of Fragment set setHasOptionsMenu() to true. To inflate different menus depending on Fragment creation clear the menu first.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
super.onCreateOptionsMenu(menu, inflater)
inflater?.inflate(Your menu here, menu)
}

Unable to add and remove menu option from fragment and navigation drawer

I am getting an issue of hiding and adding the menu item in fragment and navigation drawer as I in my application I have logout and adding contact menu and I want to set logout option in all but don't need an adding contact button in all screen. As my application contains four view pager tab fragment and navigation drawer. I have added my menu through menu XML file.
And I want my logout option in all fragment in navigation drawer but adding contact in only on my first tab fragment.
Here is code of Main Activity:
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val menuInflater = menuInflater.inflate(R.menu.main, menu)
val menuLogout = menu.findItem(R.id.logout)
val menuadd = menu.findItem(R.id.iadd_contact)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: android.view.MenuItem): Boolean {
when (item.itemId) {
R.id.logout -> {
postLogout(path, params) { response ->
}
}
return true
R.id.iadd_contact -> {
val intent = Intent(Intent.ACTION_INSERT)
intent.setType(ContactsContract.Contacts.CONTENT_TYPE)
startActivity(intent)
return true
}
}
return super.onOptionsItemSelected(item)
}
What is going with that when I move from fragment A to Fragment B i want only logout button enable and add contact disable and then when I again go revert back from Fragment B to Fragment A my add contact menu also get disable but that I want to be in Fragment A only and same as it happens when I open my navigation drawer
And in fragment I have set my code like this:
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
super.onCreateOptionsMenu(menu, inflater)
menu!!.removeItem(R.id.iadd_contact)
}
and it oncreateview:
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// TODO Auto-generated method stub
setHasOptionsMenu(false)
rootv = inflater!!.inflate(R.layout.edit_profile, container, false)
activity.invalidateOptionsMenu()
return rootv
}
Simply I just want my R.id.iadd_contact in my first tab fragment to enable and in all other fragment disable so due to fragment back stack or moving again from another fragment to my first tab fragment my add R.id.iadd_contact get also removed.
first override onCreate Method
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
And then inflate menu in your fragment
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
super.onCreateOptionsMenu(menu, inflater)
menu!!.clear()
inflater!!.inflate(R.menu.main, menu)
}

Categories

Resources