Android - How to hide menu option for current fragment - android

I have an ActionBar activity with a FrameLayout and a menu. when the user clicks the menu item I replace the fragment with the relevant new fragment. However, I cannot see an obvious way to remove the menu item for the selected fragment.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
StudyFragment startFragment = new StudyFragment();
startFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add
(R.id.container, startFragment).commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_study:
replaceFragment((Fragment)new StudyFragment());
break;
case R.id.action_list:
replaceFragment((Fragment)new ListFragment());
break;
// etc
}
return super.onOptionsItemSelected(item);
}
private void replaceFragment(Fragment f) {
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, f);
transaction.addToBackStack(null);
transaction.commit();
}
The Google documentation on changing menus says to disable the menu in onPrepareOptionsMenu - but how will I know which item has been selected?
--Solution Implemented--
Using Muhammed Refaat's solution below I added two new members to the class:
private Menu activityMenu;
private MenuItem curMenuItem;
Set them in onCreateOptionsMenu
activityMenu = menu;
curMenuItem = activityMenu.findItem(R.id.action_study);
curMenuItem.setVisible(false);
And changed them on onOptionsItemSelected
curMenuItem.setVisible(true);
curMenuItem = activityMenu.findItem(id);
curMenuItem.setVisible(false);

First get the item you want to remove :
MenuItem item = menu.findItem(R.id.your_action);
then set it's Visibility false :
item.setVisible(false);
and if the problem is in getting the menu (as it's not in the fragment), you can easily get a context from the activity that contains the menu and get the menu by it.

Inside your fragment you will have to use setHasOptionsMenu(true); in order to access options menu from within your fragment.
Code (inside your second fragment where you wanna hide the item):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO your code to hide item here
super.onCreateOptionsMenu(menu, inflater);
}
Similarly, for your fragment where you want to show that MenuItem you can do the similar thing.

In the fragment where you want to hide the Item
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item=menu.findItem(R.id.action_search);
item.setVisible(false);
and in onCreate() of your fragment
setHasOptionsMenu(true);

Adding to Muhammed's answer above. Once the item has been set as invisible, you may need to also disable the item. Note Google's comment: "Even if a menu item is not visible, it may still be invoked via its shortcut (to completely disable an item, set it to invisible and disabled)" under setVisible() in the MenuItem documentation.
Thus:
item.setVisible(false);
item.setEnabled (false);

Add below codes into your fragment
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item = menu.findItem(R.id.save);
item.setVisible(false);
}

// create Boolean variable in the main activity
private var menuvisibile: Boolean = true
// while navigating fragments set the menuvisibile value and use it
// variable as part of the return statement
invalidateOptionsMenu()
menuvisibile = false
override fun onCreateOptionsMenu(menu: Menu?): Boolean
{
val menuInflater = menuInflater
menuInflater.inflate(R.menu.notification,menu)
return menuvisibile
}
working well for me.

Related

How to hide the option menu when using getSupportFragment

Good Morning Guys,
i am trying to hide the option menu on some fragment.For the example i just want the option menu show on Promotion page
i add the code in the promotion.java
public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) {
inflater.inflate(R.menu.toolbar_menu, menu);
super.onCreateOptionsMenu(menu,inflater);
}
and then i want to hide on other fragment.
when i launching the app and the first fragment is like
but when i click to the promotion page and click back to the menu page and the action bar will be like this
i am using getSupportFragment to call the menu item, and this problem just only happen on the fragment using the getSupportFragment call out.
case R.id.menu:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MenuFragment()).addToBackStack(null).commit();
If you want to control the option menu from Fragment you must call setHasOptionsMenu(true) in onCreate() of the Fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
Clear the menu fromonCreateOptionsMenu():
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
}
OR, you can show/hide specific menu item by overriding onPrepareOptionsMenu:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item = menu.findItem(R.id.your_menu_item);
item.setVisible(false);
}
In the fragment onCreate add setHasOptionsMenu(true)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
then
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item=menu.findItem(R.id.action_search);//your id instead of action_search
item.setVisible(false);
}

Menu in fragments

I have this scenario:
I have a activity, lets call itAcitivty1 with
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return false;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
I open a fragment from Activity1 lets call it Fragment1 with:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View view = inflater.inflate(R.layout.layout, container, false);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (menu != null){
menu.clear();
}
if (!boolean) {
inflater.inflate(R.menu.menu1, menu);
} else {
inflater.inflate(R.menu.menu2, menu);
}
}
This fragment will be called again from activity as a new instance.
Based on the boolean in onCreateOptionsMenu() I'm deciding what menu should be loaded in the fragment so, during the second instance if I click on a menu item, I see the objects of first instance fragment.
I have no clue, why is this happening?
How is the workflow for displaying menu options...
if (menu != null){
menu.clear();
}
That piece of code might be the root cause.
You're telling the system to clear the menu if it's null. Well, FYI, the menu will never be null in the first place; it is supplied by the system. It might have no items inside, but it'll never be null.
One way to check if a menu already contains an item (or more) is to call hasVisibleItems().
From the documentations:
public abstract boolean hasVisibleItems()
Returns True if there is one or more item visible, else false.
Therefore, this is how you should do it:
if (menu.hasVisibleItems()){
menu.clear();
}
In a case like this, you need to put the menu in activity and update the menu dynamically in onPrepareOptionsMenu()
You need to inflate menu in onCreateOptionsMenu(..) of your Activity1 and need to make return true to display menu.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//Your code here
getMenuInflater().inflate(R.menu.main1, menu);//My menu
return true;
}
After that you get menu in your fragment also.
Edits:
If you use single menu file and show / hide MenuItem of your menu. it will solve your problem.
Add all menu in single file.by default all menu items are visible false using android:visible="false"
See example code:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem item1 = menu.getItem(0);
MenuItem item2 = menu.getItem(1);
MenuItem item3 = menu.getItem(2);
MenuItem item4 = menu.getItem(3);
if(!boolean){
//visible items which you want to show when boolean is false
item1.setVisible(true);
item2.setVisible(true);
}
else
{
//visible items which you want to show when boolean is true
item3.setVisible(true);
item4.setVisible(true);
}
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menuItem1) {
return true;
}
if (id == R.id.menuItem2) {
return true;
}
...
return super.onOptionsItemSelected(item);
}

Hide MenuItem in some Fragments

I using menu drawer which has more Fragments. In some Fragments I have menu item REFRESH but in some fragments I want hide this menu item (I don't want show menu but I don't want hide ActionBar).
I try add override onCreateOptionsMenu() to Fragment where I don't want show this menu item but I can not get it to work. I try many way see commented line in code. Does any idea where is problem? And last this menu item go to hide when I activate menu drawer when is called onPrepareOptionsMenu() in MainActivity but I need do this when I'm in Fragment.
Fragment where I want hide menu item REFRESH:
public class FindPeopleFragment extends Fragment {
public FindPeopleFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_find_people, container, false);
//setHasOptionsMenu(false);
return rootView;
}
private Menu menu=null;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.main, menu);
this.menu=menu;
menu.findItem(R.id.refresh).setVisible(false);
getActivity().invalidateOptionsMenu();
//setHasOptionsMenu(false);
super.onCreateOptionsMenu(menu,inflater);
}
}
MainActivity where is defined MENU DRAWER:
//Slide menu item click listener
private class SlideMenuClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// display view for selected nav drawer item
displayView(position);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case R.id.refresh:
Toast.makeText(this, "Refreshing data...", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
// Called when invalidateOptionsMenu() is triggered
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// if nav drawer is opened, hide the action items
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.refresh).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
In the fragment where you want to hide the Item
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item=menu.findItem(R.id.action_search);
if(item!=null)
item.setVisible(false);
}
and in onCreate() of your fragment
setHasOptionsMenu(true);
In the Fragment where you don't want to show any menu options, you need setHasOptionsMenu(false); in the onCreate(), like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
However, the menu that is being shown that you would like to hide (REFRESH), belongs to MainActivity. That is why it is always shown. Since you want to control the menu at the Fragment level (and not show an Activity options menu), my suggestion is to delete the menu code from the Activity and implement it in your Fragment.
Activitys and Fragments can each have their own separate menus. See this link.
please try this
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
}
and put this on your fragmen's onCreate()
setHasOptionsMenu(true);
In Fragment Class
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
}
in Kotlin for those who needs it
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
menu.clear()
}
I used the code below for hiding menu items in a fragment where I don't want to use it.
Note: Please read comment
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
Fragment whichFragment=getVisibleFragment();//getVisible method return current visible fragment
String shareVisible=whichFragment.getClass().toString();
if(shareVisible.equals(AccFragment.class.toString())
||shareVisible.equals(SocFragment.class.toString())
||shareVisible.equals(DevFragment.class.toString())
){
MenuItem item=menu.findItem(R.id.action_share);
item.setVisible(false);
}
return super.onCreateOptionsMenu(menu);
}
in Kotlin
override fun onPrepareOptionsMenu(menu: Menu) {
val item: MenuItem = menu.findItem(R.id.action_search)
item.isVisible = false
}
in onCreate() of your fragment
setHasOptionsMenu(true)
There are many different versions of similar solutions but unfortunately, none of them worked for me. I am sharing what eventually was useful for me to hide the whole overflow menu with multiple menu items. Thought maybe it's useful for anyone.
I grouped my menus with an id and then referred that id
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.setGroupVisible(R.id.menu_overflow, false);
super.onPrepareOptionsMenu(menu);
}
If you want to hide any individual menu item then you can use
menu.getItem(R.id.action_licenses).setVisible(false);
Important thing is that you should have setOptionsMenu(true) in onViewCreated()
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
Call setHasOptionMenu(true) in onCreateView()
and Do not call super.onCreateOptionsMenu() in fragment's onCreateOptionMenu() instead call menu.clear() because this will override the existing menu with the activity's menu
This worked in my case.
Or solve it in the same Fragment which created the menu, if you host the Actionbar on Activity level. This way you don't have to add it on every other Fragment where you don't want to show it:
public override void OnDestroy()
{
base.OnDestroy();
HasOptionsMenu = false;
}
Add these functions to your Fragment
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item=menu.findItem(R.id.delete);
item.setVisible(false);
}
Firstly in your Activity that has the toolbar, create a method that sets up the overflow menu for you:
public void setUpOptionMenu(Toolbar toolbar){
this.setSupportActionBar(toolbar);
}
In your fragments onCreateView() method, get the reference of your current activity and call your activities setUpOptionMenu() method:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
...
...
public void ((YourActivityName)this.getActivity()).setUpOptionMenu(null);
...
...
}
Cheers!!!
Overrride the following method just in your fragment and it will do the trick.
#Override
public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) {
// Do something that differs the Activity's menu here
getActivity().getMenuInflater().inflate(R.menu.drawer, menu);
}
2022 KOTLIN
On your activity, where you navigate to fragments, You can try like below, On below code, Tested on Side Navigation view, It has been shown wherever needed using toolbar.inflateMenu(R.menu.toolbar_menu) and hidden using toolbar.menu.clear() on toolbar reference.
binding.naviSideNav.setNavigationItemSelectedListener(NavigationView.OnNavigationItemSelectedListener {
when (it.itemId) {
R.id.side_nav_home->{
toolbar.title=""
toolbar.menu.clear()
toolbar.inflateMenu(R.menu.toolbar_menu)
toolbar.setBackgroundColor(ContextCompat.getColor(this,R.color.home_screen_bg))
navController.navigate(R.id.navigation_home)
}
R.id.side_nav_appointments->{
}
R.id.side_nav_ehr->{
}
R.id.side_nav_invoices->{
}
R.id.side_nav_settings->{
toolbar.title=getString(R.string.nav_menu_Settings)
toolbar.menu.clear()
toolbar.setBackgroundColor(ContextCompat.getColor(this,R.color.home_screen_bg))
navController.navigate(R.id.navigation_settings)
}
R.id.side_nav_logout->{
}
}
binding.dlt.closeDrawer(GravityCompat.START)
true
})
Clean and redraw menu item
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
inflater.inflate(R.menu.main_menu, menu)
menu.findItem(R.id.id_menu_search)?.isVisible = true
super.onCreateOptionsMenu(menu, inflater)
}
I have checked the answers but now the optionMenu has been deprecated in the latest Android api level
setHasOptionsMenu(false)
so for the people who are using MenuProvider for optionMenu can use the
setMenuVisibility(false)
like this in fragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setMenuVisibility(false)
}
Just find the item you want to hide using findItem then set its visibility to false.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem item = menu.findItem(R.id.action_settings);
item.setVisible(false);
}

Actionbar items are duplicating

I have Action Bar in my application. I am adding action items using menu.xml. I am using action bar-compat as my support library. I observed a weird issue where my action items are getting duplicated.
I am finding this issue randomly when leave my device idle or work with other applications. Please find the screen shot and my code below:
private LoginWebActivity mContext;
private final String TAG = "LoginFragment";
// for metrics
private String mPageNameSignIn = "signin";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.webview, container, false);
return mView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mContext = (LoginWebActivity) getActivity();
initFragment();
}
#Override
public void onResume() {
super.onResume();
}
/**
* Initialises the views and variables of the fragment.
*/
#SuppressLint({ "JavascriptInterface", "SetJavaScriptEnabled" })
protected void initFragment() {
mWebView = (WebView) mView.findViewById(R.id.webView);
Bundle b = mContext.getIntent().getExtras();
if (b != null) {
mUrl = b.getString(Constants.EXTRA_WEB_LOGIN_URL);
}
super.initFragment();
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.signin, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Navigate
switch (item.getItemId()) {
case R.id.menu_item_signup:
mContext.onSignUpClick();
break;
case android.R.id.home:
if (!goBack())
getActivity().finish();
default:
break;
}
return super.onOptionsItemSelected(item);
}
My XML :
<?xml version="1.0" encoding="utf-8"?>
<item
android:id="#+id/menu_item_signup"
allergy:showAsAction="ifRoom"
android:title="#string/sign_up">
</item>
You must clear your menu object before adding items. I had the same problem and this was the best solution that I've found.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.signin, menu);
super.onCreateOptionsMenu(menu, inflater);
}
Pretty late to this party, but for anyone that comes across this via the Google like I did, here's the real problem.
You didn't post your Activity code that's creating the Fragment, but I will venture to guess that it looks something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Fragment fragment = ...
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
The problem with this is that when the activity goes through its lifecycle (which would happen "when leave my device idle or work with other applications", as you say), the system will save and restore the state of fragments for you. But with this code, you also are adding a new fragment to your Activity, so you end up with multiple fragments running in your activity, each adding an item to the menu.
While the posted workaround will address the duplicate menu entries issue, it would leave these extra fragment instances lying around, which is obviously not what you want.
The correct fix is a simple null check:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
if (savedInstanceState == null) {
Fragment fragment = ...
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
}
Since the system will indicate the activity is being recreated with a non-null Bundle for the savedInstanceState parameter, you check this to determine whether you should be creating and adding a new fragment.
Hope that helps.
i used Renan Bandeira's great solution and i had some error so i changed it a little bit and worked for me too . then I'm sharing my experience : maybe it become helpful again all credit goes to him for great solution .
#Override
public void onCreateOptionsMenu(Menu menu ) {
menu.clear();
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu."your current activity name ", menu);
return true;
}
I facing the same problem and exactly as state by #Szymon "I add menu option from the fragment, I create multiple fragments?" So my solution was look like below.
onCreate :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.menu, menu);
menu.findItem(R.id.action_one).setVisible(true);
menu.findItem(R.id.action_two).setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
onPrepare :
#Override
public void onPrepareOptionsMenu(Menu menu) {
if (isAdded()
&& !isDetached()
&& isVisible()
&& !isRemoving()
)
{
// show the menu
if (menu.findItem(R.id.action_one).isVisible())
menu.findItem(R.id.action_one).setVisible(true);
// hide the menu
if (menu.findItem(R.id.action_two).isVisible())
menu.findItem(R.id.action_two).setVisible(false);
}
}
You should use the following method instead and you will not see the duplicates anymore (notice that it has only a Menu object as argument)
#Override
public boolean onCreateOptionsMenu( Menu menu )
{
getMenuInflater().inflate( R.menu.main_activity_menu, menu );
return true;
}

(Deprecated) Fragment onOptionsItemSelected not being called

EDIT:
This question was for the deprecated sherlock action bar. Android support library should be used instead now
I have added an action bar menu option called share for my fragment which appears but the selection event is not being caught
I am adding it like this
#Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
MenuItem item = menu.add(0, 7,0, R.string.share);
item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
Trying to capture it in both the fragment and the fragment activity like
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 7:
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
startActivity(Intent.createChooser(share, "Share Text"));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
and I have setHasOptionsMenu(true); in the onCreate().
Same problems happened to me:
onMenuItemSelected events didn't get called in Fragment
Searched google cann't find a solution, and add onMenuItemSelected method in FragmentActivity doesn't solve it.
Finally resolve it by following reference to http://developer.android.com/guide/topics/ui/actionbar.html
Note: If you added the menu item from a fragment, via the Fragment class's onCreateOptionsMenu callback, then the system calls the respective onOptionsItemSelected() method for that fragment when the user selects one of the fragment's items. However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected() on the activity before calling the same callback for the fragment.
Which means only if you don't have that menu item handler in onOptionsItemSelected() on the activity, the onOptionsItemSelected() on the fragment will be called.
Code as following
-----Remove the handler for R.action.add on FragmentActivity):
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
popBackStack();
return true;
case R.id.action_search:
searchAction();
return true;
case R.id.action_logout:
userLogout();
return true;
//case R.id.action_add:
//return true;
default:
return super.onOptionsItemSelected(item);
}
}
And the handler for R.action.add on Fragment looks like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("onOptionsItemSelected","yes");
switch (item.getItemId()) {
case R.id.action_add:
add();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Finally, remember to add
setHasOptionsMenu(true);
in your onCreate method in Fragment
I had the same problem, but I think it's better to summarize and introduce the last step to get it working:
Add setHasOptionsMenu(true) method in your Fragment's onCreate(Bundle savedInstanceState) method.
Override onCreateOptionsMenu(Menu menu, MenuInflater inflater) (if you want to do something different in your Fragment's menu) and onOptionsItemSelected(MenuItem item) methods in your Fragment.
Inside your Activity's onOptionsItemSelected(MenuItem item) method, make sure you return false when the menu item action would be implemented in Fragment's onOptionsItemSelected(MenuItem item) method.
An example:
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.activity_menu_item:
// Do Activity menu item stuff here
return true;
case R.id.fragment_menu_item:
// Not implemented here
return false;
default:
break;
}
return false;
}
Fragment
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
....
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Do something that differs the Activity's menu here
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.activity_menu_item:
// Not implemented here
return false;
case R.id.fragment_menu_item:
// Do Fragment menu item stuff here
return true;
default:
break;
}
return false;
}
I have noticed that the solution people gave you was to implement the code for your menue item in the activity rather then the fragment.
I think it will look much more orgenized if you had implemented the code in the fragment rather then the activity 'cos in my opinion it looks better.
To do so, do as follows :
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.SomeIDInTheMenueOfTheActivity:
{
//something();
break;
}
default:
//do something default and add the code under :
return super.onOptionsItemSelected(item);
}
return true;
}
Fragment
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.SomeIDInFragmentMenue:
{
break;
}
default:
return super.onOptionsItemSelected(item);
}
return true;
}
Now the lines (and the likes): "return super.onOptionsItemSelected(item);" in the activity and fragment are super important, because as if you will follow the code in debug, you will see that the menue events functions will be called first on the Activity, and if the item did not match the id's in the activity's switch-case, the degault line : "super.onOptionsItemSelected(item);" will call the onOptionsItemSelected function on the fragment, as we wanted.
(if you have many fragments, make sure to have that line in them as well, as the calling hirarchy can be somewhat complicated).
I'm using actionbarsherlock. This worked for me:
1) Create dummy_menu.xml menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
<item
android:title=""
android:showAsAction="never"
android:id="#+id/dummyMenu"
/>
2) In activity inflate the menu like this:
#Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.dummy_menu,menu);
return super.onCreateOptionsMenu(menu);
}
3) In fragments onCreateView call setHasOptionsMenu(true) and override onCreateOptionsMenu and onOptionsItemSelected also hide the dummyMenu like this (in fragment)
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_actions, menu);
MenuItem item = menu.findItem(R.id.dummyMenu);
item.setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
Hope it helps someone.
Edit for actionbar sherlock use
I had to use
public boolean onMenuItemSelected(int featureId, MenuItem item) {
in the main activity to capture the menu item
it's so simple you can do that in your fragment to make sure that your action will listen correctly:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
From the documentation, it should solve by this steps:
If you in Activity Using the addMenuProvider() API directly:
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
}
})
}
}
If you in Fragment Using the addMenuProvider() API
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)
}
I had this problem. It was because I was overiding the wrong method
onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item)
is what I used.
Make sure you are using the right one!
You are not chaining to the superclass in the activity methods. Please have onCreateOptionsMenu() return super.onCreateOptionsMenu(menu), and have onOptionsItemSelected() return super.onOptionsItemSelected(item) (except for the item that you are handling, which should return true to indicate that you have handled the event)
you must add this code toolbar.bringToFront(); next set toolbar in your activity
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
...
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle("Yazd");
setSupportActionBar(toolbar);
toolbar.bringToFront(); // <<= add here
...

Categories

Resources