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.
Related
Currently I have action bars for each fragment, when I swipe the fragment a new actionbar appears in place of the old one. What I want to do is when I swipe, I want to swipe away the actionbar and place it with a new one. Each fragment should have their own actionbar.
I'm not sure if its making complete sense so I drew a quick demonstration of what I'm trying to do.
In your viewpager container (Activity or Fragment), add the next line in your page change listener:
invalidateOptionsMenu();
supportInvalidateOptionsMenu();//if using the actionbar support library
getActivity().invalidateOptionsMenu();//if your viewpager container is a fragment
Then in your onCreateOptionsMenu(),
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.your_menu_layout, menu);
}
The onPrepareOptionsMenu() callback method is called before the menu is shown, and we are going to use it to make the menu items visible depending on the current fragment:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
int page = yourViewPager.getCurrentItem();
switch(page) {
case 0:
menu.findItem(R.id.item_f1).setVisible(true);
menu.findItem(R.id.item_f2).setVisible(false);
menu.findItem(R.id.item_f3).setVisible(false);
break;
case 1:
menu.findItem(R.id.item_f1).setVisible(false);
menu.findItem(R.id.item_f2).setVisible(true);
menu.findItem(R.id.item_f3).setVisible(false);
break;
case 2:
menu.findItem(R.id.item_f1).setVisible(false);
menu.findItem(R.id.item_f2).setVisible(false);
menu.findItem(R.id.item_f3).setVisible(true);
break;
}
return true;
If your viewpager container is a fragment, add setHasOptionsMenu(true), if it is an activity it's not necessary.
Reference - Swipe view with different actionbar items in each swipe fragment
You could be using the Toolbar from the AppCompat library. Add a view to this Toolbar, which you move based on the position of your ViewPager. For making such a view, check this question.
You could also try multiple Toolbars, which might be possible, but it is not supported. Which could result in breaking your app, if the AppCompat library does get updated. Although it looks like it is possible, according to this question.
I don't think this can be done with ActionBar, Its just too limited... I've just went ahead and made my own custom layout that I use on my fragments.
Since i'm implementing a lot of features into my actionbar I'm probably best of customizing my own.
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 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.
My app uses tab navigation with Actionbar Sherlock to switch between two fragments each with their own listview. Also, each fragment has it's own options menu associated with it, so within my two fragment classes I've made use of:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
...
}
For one of the fragments, its important to have some of the options in its options menu greyed out depending on which items the user has selected in its list. I've done this by calling:
#Override
public void onPrepareOptionsMenu(Menu menu){
...
}
Within this method, I identify which items in the list have been checked. I've noticed that when I switch between tabs, onPrepareOptionsMenu get called right away. Then the very next time I press the menu key, onPrepareOptionsMenu is not called, and the available options in the menu are not updated. When I hit the menu button a second time, everything works fine and the available options get updated. Is there I way I can enforce onPrepareOptionsMenu gets called when the menu key is pressed following a tab switch?
I've seen notes about using invalidateOptionsMenu() to trigger onPrepareOptionsMenu, but it seems messy to override the menu key event every time while this issue only comes up the first time the user presses the menu key. Is there a better way?