I can't work MenuProvider in Fragment for menu - android

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

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

kotlin android "OnbackPressed" overrides nothing

I know this already asked a few times, but I still don't get anything after all (I'm quite new in android development).
So i set up my back button in the MainActivity.kt like this:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
val navController = this.findNavController(R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this, navController)
supportActionBar?.setDisplayHomeAsUpEnabled(false)
}
// Set up the back button on action bar
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return navController.navigateUp()
}
}
What I want is that this back button is disabled in some fragments, so I tried to override the onBackPressed() function (It is what most people on the internet told) in one of the fragments:
class DashboardFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Declare that this fragment has menu
setHasOptionsMenu(true)
// Set action bar title to "Main Dashboard"
(activity as AppCompatActivity).supportActionBar?.title = "Main Dashboard"
// Binding object for this fragment and the layout
val binding: FragmentDashboardBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_dashboard, container, false)
//Some codes here//
return binding.root
}
// This is where the error occured
override fun onBackPressed() {
super.onBackPressed()
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater?.inflate(R.menu.nav_overflow_menu, menu)
}
}
But it returns an error saying:
"OnBackPressed" overrides Nothing
Am I missing something? I'm already searching for the solutions but still confused over this.
Who knew... onSupportNavigateUp() works only on 4.0 and above. For below onNavigateUp() is called.
so
override fun onNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return navController.navigateUp()
}
What you could do is set your nonbackbutton fragments to backstack when inserting them, which is done by
val transaction = supportFragmentManager.beginTransaction()
transaction.addToBackStack(null)
transaction.replace(R.id.frame, fragment) //or add, whatever you use
transaction.commit()
(if you want back button functionality, just skip the addtoBackStack line)
Then, also in your activity, you override the onBackPressed() and check whether the backstack is empty or full. If it is empty, which is checked by
if(supportFragmentManager.backStackEntryCount() == 0)
then you are, for example, on a fragment that supports back button, and just do super.onBackPressed().
On the other hand, if it has something, you can do the navController.navigateUp() part, and when done, pop it using supportFragmentManager.popBackStackImmediate().
I think you could make something like this work, try it, and let us know :)

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