I need to make two minor changes to an Activity's ActionBar from a Fragment.
The parent FragmentActivity's onCreateOptionMenu and onPrepareOptions handle the menu across the app.
However, in the containing main Fragment view, I want the ActionBar title to change for the sake of navigation. Each time the Fragment changes.
Also, in one instance, I want to add a single menu item as defined in the layout. I rather not duplicate code for this part, do I have to override the same methods and set up entire menu again, including onOptionSelected? Or...?
Edit:
On my menu xml layout, I have this item:
<item
android:id="#+id/Add"
android:title="Add Items"/>
This item needs to be seen in the ActionBar only for one particular Fragment. The rest of the menu is identical to what should be seen for the rest of the app. In the fragment where I need this new item, do I have to also do onCreateOptionsMenu, onPrepareOptionsMenu, and onOptionsItemSelected all over again and duplicate thee OTHER menu items as well? Or can I override those in the Fragment and just pop that one extra menu item in?
1.
getActivity().getActionBar().setTitle();
or
getActivity.getSupportActionBar().setTitle();
more clarification please :)
This answered what I needed for part 2.
Putting this in onActivityCreated:
setHasOptionsMenu(true);
And then adding this too:
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
ActivityCompat.invalidateOptionsMenu(getActivity());
MenuItem Add = menu.findItem(R.id.Add);
Add.setVisible(true);
}
The parent Activity sets the R.id.Add as invisible by default.
Related
I am learning android and I am a bit unsure about how menu options work.Here is the set up I have,
I have a main activity which has a fragment inside it. Main activity's onCreateOptionsMenu looks like this
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
This menu_main.xml just has settings button. I was supposed to add a refresh button in the fragment so I created a new menu xml and added this code in the fragment class
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.tempfragment, menu);
}
When I ran the app and did the longpress, I saw both refresh and setting button.
My question is that when we have a menu options for main activity and for a its associated fragment, what is the flow like? Does it combine both of the menus? I can see it is combining but I am bit unsure regarding how it is getting handled internally? Can somebody explain this to me?
Edit
Here is menu file for the fragment
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item android:id="#+id/action_refresh" android:title="action_refresh"
app:showAsAction="never"
/>
</menu>
If you have a MainActivity that inflates an options menu, menu_main.xml, then that options menu will always be present on any fragment that the MainActivity creates.
Within each fragment code, you can create options menus for that specific fragment. Say you inflate menu_friends.xml in FriendsFragment. When an instance of FriendsFragment is created by MainActivity, both menu_main.xml and menu_friends.xml will be shown. You can repeat this for all fragments.
Edit: #Kartheek is incorrect with his answer regarding calling setHasOptionsMenu(true) in a fragment cancelling out the activity's menu. All that statement does is allow a menu to be created by that fragment. Both menus will be included. See here:
Calling setHasOptionsMenu(true) from a fragment results in multiple calls to onCreateOptionsMenu in Activity
Dont forgent thet the main activity conties the fragment, and the actionbar is in the activity, so if you change the fragment its not like you change the activity...
Becuse of it the action bar not change, its just combiens between the action bar thet you have already in the activity, and the actionbar thet you have in the fragment.
Hope its help you :)
when we have a menu options for main activity and for a its associated
fragment ?
If your fragment has called the setHasOptionsMenu to true then onCreateOptionsMenu will be called in your fragment and also in your activity.It actually combines the menu items of the Activity and the Fragment.
Does it combine both of the menus?
Yes. It combines both of them it displays them in a whole.
Can somebody explain this to me?
You can declare items for the options menu from either your Activity subclass or a Fragment subclass. If both your activity and fragment(s) declare items for the options menu, they are combined in the UI. The activity's items appear first, followed by those of each fragment in the order in which each fragment is added to the activity. If necessary, you can re-order the menu items with the android:orderInCategory attribute in each <item> you need to move.
If your activity includes fragments, the system first calls onOptionsItemSelected() for the activity then for each fragment (in the order each fragment was added) until one returns true or all fragments have been called.
I have a 3 page Fragment in my app, but I need each fragment to have a different ActionBar. For one fragment I have set the current code in the OnCreateView method that adds in an EditText to the ActionBar:
//mainActivityContext is the context for the Main Activity (This is a fragment file)
ActionBar actionBar = mainActivityContext.getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
Yet this EditText stays persistent throughout all of the ActionBar menus. I only want it on one. I have tried everything, menu.clear();, setHasOptionsMenu(true);, inflater.inflate(R.menu.different_file, menu);, but nothing has worked.
Any help?
There is a very good approach to go about this situation:
on each fragment's onActivityCreated() method call setHasOptionsMenu(true);
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
now you can override onCreateOptionsMenu() and onOptionsItemSelected() inside each fragment.
And also dont forget to call getActivity().supportInvalidateOptionsMenu(); inside onResume() of fragment.
I think this sample by google will be very helpful.
Since the actions are populated by the activity's options menu you can use Activity#invalidateOptionsMenu(). This will dump the current menu and call your activity's onCreateOptionsMenu/onPrepareOptionsMenu methods again to rebuild it.
If you're using action bar tabs to change your fragment configuration there's a better way. Have each fragment manage its own portion of the menu. These fragments should call setHasOptionsMenu(true). When fragments that have options menu items are added or removed the system will automatically invalidate the options menu and call to each fragment's onCreateOptionsMenu/onPrepareOptionsMenu methods in addition to the activity's. This way each fragment can manage its own items and you don't need to worry about performing menu switching by hand.
I have an activity which has 2 fragments.
1 fragment is visible at a time and each fragment has a different option menu.
I can achieve this behavior by 2 different ways.
1 - I can add different menu for each fragment by calling onCreateOptionsMenu in each friengment.
2 - I can have only one menu at activity level and can select to show particular option in onPrepareOptionsMenu
What I want to know is:
Which is the preferable way to implement this functionality?
What is recommended?
Hope this helps
Adding items to the Action Bar
Your fragments can contribute menu items to the activity's Options Menu (and, consequently, the Action Bar) by implementing onCreateOptionsMenu(). In order for this method to receive calls, however, you must call setHasOptionsMenu() during onCreate(), to indicate that the fragment would like to add items to the Options Menu (otherwise, the fragment will not receive a call to onCreateOptionsMenu()).
Any items that you then add to the Options Menu from the fragment are appended to the existing menu items. The fragment also receives callbacks to onOptionsItemSelected() when a menu item is selected.
You can also register a view in your fragment layout to provide a context menu by calling registerForContextMenu(). When the user opens the context menu, the fragment receives a call to onCreateContextMenu(). When the user selects an item, the fragment receives a call to onContextItemSelected().
http://developer.android.com/guide/components/fragments.html
I would follow the first option as having a dedicated resource menu for each fragment seems cleaner and also reduces the code complexity you would have in order to maintain what is visible and what is not (if you would go through onPrepareOptionsMenu and have code to hide & show different menus).
If you have some actions in your fragments, then you could create a base fragment class that each of your fragments would extend from.
For each Fragment I will add Menu Items to provide the user with context related actions. But when switching to another Fragment, the Menu items stayed. So I can end with all options from each fragment in the menu.
How do you clean the menu item to have only the ones set up in the activity menu?
I read about invalidateOptionMenu() and onPrepareOPtionmenu() but I don't really get how they work. What is the correct way to implement it ?
Anyway, how is it that removing fragment-linked menu item when the fragment is not displayed anymore is not native Android behavior?
EDIT if instrucitons not clear enough.
I have one activity supporting Navigation_Mode_Tabs with settings as global menu item.
I start fragA that add itemA1 and itemA2. So I have setting, itemA1, itemA2. So far, so good.
Then I switch to fragB that add its own itemB. HERE, I have settings, itemA1, itemA2, itemB in the menu !
Why itemA1 and itemA2 are stuck? How to remove them?
EDIT 2 : I have try another set up of tabulation from this post and it suddenly menu items seems to be correctly remove !
It's something to see with the use of remove(R.id.container, fragment) versus the onDetach()/onAttach() that Google recommands here
I am looking at this, probably tomorrow I'll update. Please, if you know about this, share :)
you could set the menuinflater on each activity.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.demo, menu);
return true;
}
You should add TabListener to your tabs and call supportInvalidateOptionsMenu() in onTabSelected() method. It cause call onCreateOptionsMenu(). You should override it in your activity and inflate menu for selected fragment. If you add menu items from code don't forget to clear menu for previous fragment.
I have 3 Fragments which, in a normal (small) layout are all in separate Activities. They should provide an optionsmenu in the small layout.
In the large layout, I have the 3 fragments in one Activity, causing the menu to fill with the buttons inflated by all three fragments. How can I prevent this, and only let the Activity inflate the optionsmenu, while still holding the functionality on smaller devices?
-Edit-
So each Fragment uses the following code:
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
/* Some code */
setHasOptionsMenu(true);
/* Some code */
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.mymenu, menu);
}
When all three Fragments are shown, all Fragments execute onCreateOptionsMenu() and all items appear three times.
What I want is for the parent Activity to take the responsibility of creating the options menu.
In each Fragment I would build the entire menu. What I've done is, to add in the Fragments only their specific menu items, and in the parent Activity I would build the general items.
You could use the isVisible() method on each Fragment to dynamically check which is being displayed and then add appropriately within the Activity.