I have one activity with 3 fragments (not tabs). I have several action bar items and I would like to hide them when a certain fragment is present. How can i go about this?
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem item3 = menu.findItem(R.id.ID OF MENU);
item3.setVisible(false);
}
If you wish to hide ALL menu items, just do:
#Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
setHasOptionsMenu(true);
}
#Override
public void onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.clear();//This removes all menu items (no need to know the id of each of them)
}
What i understand with your post is::
You have 3 fragments
You have 3 different set of actionbar buttons for 3 fragments
My preferred approach::You can also find the menu items which you dont want to display in your current fragment and set their visibility
MenuItem item = menu.findItem(<id>);
item.setVisible(<true/false>);
ex::
MenuItem item1 = menu.findItem(R.id.searchID);
item1.setVisible(false);
You can also use this post for a different approach to handle this problem
Related
How can I access my Menu from my fragment and then change the icon of one of the menu items there?
What I am doing is querying my local DB to see if a certain entry exists when the fragment is shown. If it does display a solid icon, if not, display an outlined icon.
In your fragments onCreate() method you can use setHasOptionsMenu(true) to allow your fragment to handle different menu items than it's root Activity.
So you could do something like this in your fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
And then, you can override any of the menu life-cycle methods in your fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_fragment, menu);
// You can look up you menu item here and store it in a global variable by
// 'mMenuItem = menu.findItem(R.id.my_menu_item);'
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem menuItem = menu.findItem(R.id.menu_item_to_change_icon_for); // You can change the state of the menu item here if you call getActivity().supportInvalidateOptionsMenu(); somewhere in your code
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
// Handle actions based on the id field.
}
I found a simpler way of doing it than in the provided answer:
Toolbar toolbar = requireActivity().findViewById(R.id.toolbar);
Menu menu = toolbar.getMenu();
MenuItem item = menu.findItem(R.id.item_settings);
item.setIcon(R.drawable.ic_settings);
Access the menu from the toolbar.
In my app I set the toolbar and status bar as shared objects as suggested in option #2 in this post
The general behavior and outline of the toolbar and tabs are excellent - the only issue is that when I move to activity B, some of the UI elements of the Toolbar are not participating in the content transition, particularly the Toolbar title and the menu icons.
I tried adding a SharedElementCallback and in it to loop over the children of the toolbar and tabs and add them all to a Fade transition - but it didn't affect the behaviour of the toolbar and tab content.
Any idea how to proceed from here? The desired effect is to have the elements of the Toolbar (title, up button, menu icons) participate in the content transition.
Added screenshots after comment:
Activity A
Activity B
Each activity has your own menu, so you have to create the menu for each one, even if they are the same.
However, if you prefer, you can create just one menu and create a custom class for manipulate the menu; Then you call this custom class on onCreateOptionsMenu and onOptionsItemSelected from whatever activity.
The following code is an example.
Custom class:
public class MenuActionBar {
public static void createOptionsMenu(final Activity activity, Menu menu) {
activity.getMenuInflater().inflate(R.menu.yourmenu, menu);
// Do whatever you wanna do
}
public static boolean optionsItemSelected(Activity activity, MenuItem item) {
// Do whatever you wanna do
}
}
Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuActionBar.createOptionsMenu(this, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return MenuActionBar.optionsItemSelected(this, item)
? true : super.onOptionsItemSelected(item);
}
My menu has a item to Log in, but when you are logged in I want it to say Log out.
How?
If I'm going to change the item after its created, its probably through this method
#Override
public boolean onCreateOptionsMenu( Menu menu ) {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.menu_main, menu );
return true;
}
Afaik the onCreateOptionsMenu() happens after the onCreate so putting any getItemId() for the menu there will give me a NullPointerException right away.
I want the app to find out if its supposed to use the string R.string.Logout if its logged in.
I dont even know what to search for for this issue. All I found was how to make a string implement names, like this answer https://stackoverflow.com/a/7646689/3064486
You should use onPrepareOptionsMenu(Menu menu) instead to update menu items
#Override
public boolean onPrepareOptionsMenu(Menu menu){
super.onPrepareOptionsMenu(menu);
MenuItem someMenuItem = menu.findItem(R.id.some_menu_item);
someMenuItem.setTitle("Log out");
return super.onPrepareOptionsMenu(menu);
}
To refresh Menu items call invalidateOptionsMenu();from Activity
From Android API guides: "If you want to modify the options menu based on events that occur during the activity lifecycle, you can do so in the onPrepareOptionsMenu() method. This method passes you the Menu object as it currently exists so you can modify it, such as add, remove, or disable items. (Fragments also provide an onPrepareOptionsMenu() callback.)"
After you inflate a menu, you can customize its items. To get each one, you must call findItem() with the item's id. In particular, you can use setTitle() to change the displayed string.
For example:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (mIsLoggedIn)
menu.findItem(R.id.action_login).setTitle("Log out");
return true;
}
where action_login is the id you set for this particular menu item in the menu's xml file.
private void updateUI() {
runOnUiThread(new Runnable() {
#Override
public void run() {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu menu = navigationView.getMenu();
MenuItem nav_signin = menu.findItem(R.id.nav_signin);
nav_signin.setTitle(MyApp.signedIn ? "Sign out" : "Sign in");
}
});
}
I am creating android application and I'm trying to respect as much as possible the latest Android usability standards. In particular, I am preparing the user interface using the navigation drawer, and I'm trying to ensure compatibility with 2.1+ Android versions. To appreciate the problem, the project consists of:
A main activity;
A navigation drawer;
Four fragments (with their associated layouts).
The problem I'm experiencing occurs when opening the navigation drawer: although each Fragment has its specific menu, when I open the navigation drawer it is added to the nav drawer menu. I tried in several ways (invalidateOptionMenu(), menu.clear(), manipulating functions isDrawerOpen() and isDrawerClose() and more), but I cannot remove the Fragment's menu when opening the navigationdrawer.
These are some snippets of my code, much of it generated by Android Studio, the IDE I'm using:
In main activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.global, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
where "global" is a simple menu with a classical "ic_action_overflow".
And in my fragments I've:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment1, menu);
}
(It's the same of the other Fragments).
Someone can give me some advice on how to act?
I faced the same problem using the boilerplate code generated by Android Studio and got it working by modifying the menu in NavigationDrawerFragment.onPrepareOptionsMenu() (in my case, I wanted to clear the menu altogether):
#Override
public void onPrepareOptionsMenu(Menu menu) {
if (mDrawerLayout != null && isDrawerOpen()) {
menu.clear();
}
}
This is roughly how the options menu is recreated:
NavigationDrawerFragment, which is generated by the IDE, calls supportInvalidateOptionsMenu() when the drawer is opened or closed.
onCreateOptionsMenu gets called: The hosting activity and each of the added fragments gets a chance to contribute menu items.
onPrepareOptionsMenu gets called: Again, the hosting activity and each of the added fragments get a chance to modify the menu.
The fragments are iterated in the order they were added. There is no way to stop the chain of calls midway in steps 2. and 3.
So the idea is to let NavigationDrawerFragment do last-minute changes to the menu in its onPrepareOptionsMenu and no other fragments.
If you need to let other fragments do something in onPrepareOptionsMenu, then you may have to setup those other fragments so they can determine if the drawer is open or not and change their behavior accordingly. This may mean perhaps adding a isDrawerOpen method to the hosting activity or passing in the drawer identifiers to the fragment like it's done in NavigationDrawerFragment.setup().
In your fragment onCreate, add this :
setHasOptionsMenu (true);
And then hide through onPrepareOptionsMenu. e.g.
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.action_settings).setVisible(false);
}
If you've implemented the navigation drawer the way Android Studio sets it up for you in its example code with a NavigationDrawerFragment, you should have two xml to start with main.xml (activity wide actionbar menu items) and global.xml (global items). I then added a fragment specific menu which adds items to the "activity menu items" as long as the drawer is closed...
Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this activity
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
this.menu = menu;
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
NavigationDrawerFragment
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// If the drawer is open, show the global app actions in the action bar.
// See also showGlobalContextActionBar, which controls the top-left area
// of the action bar.
if (mDrawerLayout != null && isDrawerOpen()) {
inflater.inflate(R.menu.global, menu);
showGlobalContextActionBar();
}
super.onCreateOptionsMenu(menu, inflater);
}
and in your fragments add as you've described above
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Add fragment specific action bar items to activity action bar items.
// Activity wide items are in main.xml
// Visible action bar items if navigation drawer is visible/open
// are in global.xml
super.onCreateOptionsMenu(menu, inflater);
if (!mNavigationDrawerFragment.isDrawerOpen()) {
inflater.inflate(R.menu.fragment_menu, menu);
}
}
Check out this answer here: https://stackoverflow.com/a/18135409/2558344. Its basically using a boolean to clear items in the navigation drawer and vice versa. But alternatively, you could declare Menu menu as a private variable in your class and use it as: onCreateOptionsMenu(menu, MenuInflater inflater).
Then check in your fragments onStop(), onPause() if it's displaying items or not, if yes then clear them, like:
if (menu != null)
menu.clear();
In some methods of my Activity I want to check the title of menu or know if it is checked or not. How can I get Activity's menu. I need something like this.getMenu()
Be wary of invalidateOptionsMenu(). It recreates the entire menu. This has a lot of overhead and will reset embedded components like the SearchView. It took me quite a while to track down why my SearchView would "randomly" close.
I ended up capturing the menu as posted by Dark and then call onPrepareOptionsMenu(Menu) as necessary. This met my requirement without an nasty side effects. Gotcha: Make sure to do a null check in case you call onPrepareOptionsMenu() before the menu is created. I did this as below:
private Menu mOptionsMenu;
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mOptionsMenu = menu
...
}
private void updateOptionsMenu() {
if (mOptionsMenu != null) {
onPrepareOptionsMenu(mOptionsMenu);
}
}
Call invalidateOptionsMenu() instead of passing menu object around.
you could do it by passing the Menu object to your Activity class
public class MainActivity extends Activity
{
...
...
private Menu _menu = null;
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
_menu = menu;
return true;
}
private Menu getMenu()
{
//use it like this
return _menu;
}
}
There several callback methods that provide menu as a parameter.
You might wanna manipulate it there.
For example:
onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
onCreateOptionsMenu(Menu menu)
onCreatePanelMenu(int featureId, Menu menu)
There several more, best you take a look in activity documentation and look for your desired method:
http://developer.android.com/reference/android/app/Activity.html
As far as I could understand what you want here is which may help you:
1. Refer this tutorial over option menu.
2. Every time user presses menu button you can check it's title thru getTitle().
3. Or if you want to know the last menu item checked or selected when user has not pressed the menu button then you need to store the preferences when user presses.
Android now has the Toolbar widget which was a Menu you can set/get. Set the Toolbar in your Activity with some variation of setSupportActionBar(Toolbar) for stuff like onCreateOptionsMenu from a Fragment for example. Thread revived!