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

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)
}

Related

Back arrow won't trigger onOptionsItemSelected

I want add confirmation dialog before my fragment close. I have added the onOptionsItemSelected function in my fragment. however when i click the back arrow button the function is not executed. Here's my code
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(activity as AppCompatActivity).supportActionBar?.show()
(activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)
(activity as AppCompatActivity).supportActionBar?.setDisplayShowHomeEnabled(true)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_input, menu)
return super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> "testing".debugTag("Debug")
}
return super.onOptionsItemSelected(item)
}
Try to set the action bar in onCreate.
setSupportActionBar( yourActionBar );

Unwanted navigation when tapping OptionsMenu Item in Fragment

My application has one Activity and several fragments. Navigation Component was used for navigation and it is not very complicated. Also BottomNavigationComponent was used for bottom navigation.
There are three top level fragments which can be accessed via bottom navigation and there is an options menu at one of the top level fragments. Also this is not a complicated menu,too; there is just one item.
So, this is not a big deal and created menu like below.
notifications_menu
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/dismiss_all"
android:title="#string/dismiss_all"
android:orderInCategory="10"
app:showAsAction="ifRoom" />
</menu>
NotificationsFragment.kt
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel =
ViewModelProvider.NewInstanceFactory().create(NotificationsViewModel::class.java)
setHasOptionsMenu(true)
(activity as MainActivity).supportActionBar?.setDisplayHomeAsUpEnabled(false)
(activity as MainActivity).supportActionBar?.setDisplayShowHomeEnabled(false)
//other stuff
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.notifications_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == R.id.dismiss_all) {
// there is no code here yet
return true
}
return super.onOptionsItemSelected(item);
}
And here is the result...
The problem is, as you can see above, when I tap Dismiss All button it navigates to the initial fragment. But I couldn't understand why?
After digging two hours I found that MainActivity's onOptionsItemSelected is causing this situation. Because as you can see it is handling all menu items and call onBackPressed event.
override fun onOptionsItemSelected(menuItem: MenuItem?): Boolean {
if (menuItem != null) {
onBackPressedDispatcher.onBackPressed()
}
return super.onOptionsItemSelected(menuItem)
}
Handling correctly this method solved my problem.
Here is the correct version of the code above.
override fun onOptionsItemSelected(menuItem: MenuItem?): Boolean {
val id = menuItem?.itemId
if (id == android.R.id.home) {
onBackPressedDispatcher.onBackPressed()
return true
}
return super.onOptionsItemSelected(menuItem)
}

Show menu actions only in certain fragments - NavigationComponents

I have a navigation host activity that inflates 2 fragments, one the main host fragment and the event fragments, I need to show in the event fragment a menu action , but this menu action is also shown in the main fragment which I dont want to show
How do I show this menu only in the event fragment ?
MainActivity
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = Navigation.findNavController(this, R.id.nav_host_fragment)
setupActionBar(navController)
}
private fun setupActionBar(navController: NavController) {
NavigationUI.setupActionBarWithNavController(this, navController)
}
override fun onSupportNavigateUp(): Boolean {
return Navigation.findNavController(this, R.id.nav_host_fragment).navigateUp()
|| super.onSupportNavigateUp()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
MenuInflater(this).inflate(R.menu.menu, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
NavigationUI.onNavDestinationSelected(item!!, Navigation.findNavController(this, R.id.nav_host_fragment))
return super.onOptionsItemSelected(item)
}
Menu
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/eventsFragment"
app:showAsAction="ifRoom|always"
android:title="¿ Where to buy ?" />
</menu>
I need to show this menu only in the eventsFragment
EventFragment
class EventsFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_event, container, false)
}
But instead of just showing it just in the EventFragment it also shows it in the first fragment that MainActivity as hosts inflates
How can I just have this menu in my EventsFragment?
In MainActivity menuItem setVisible(false):
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
MenuInflater(this).inflate(R.menu.menu, menu)
val menuItem : MenuItem = menu.findItem(R.id.eventsFragment);
if (menuItem!= null)
menuItem.setVisible(false);
return super.onCreateOptionsMenu(menu)
}
In EventsFragment setvisibility of menuitem to true as shown below:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onPrepareOptionsMenu(menu: Menu) {
val menuItem = menu.findItem(R.id.eventsFragment)
if (menuItem != null)
menuItem.isVisible = true
}
You could try considering Inflating the menu from inside the fragment. ie. fragments onCreate() method and destroying it from onDestroy() function of the fragment

OptionsMenu in nested fragments with Nav component

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.

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)
}

Categories

Resources