Android: How to recreate Action bar when fragment changed - android

I have an activity showing a few fragments.
Activity view contains only ViewPager initialized with custom FragmentPagerAdapter.
This adapter provide navigation among 3 fragments.
All seems to work fine except Action bar.
I override onCreateOptionsMenu() method in my fragments to create individual Action bar for any fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
//fragment specific menu creation
}
When I do swipe, new fragment appears, but Action bar stay the same for a few seconds. Probably after a few seconds this method are called and Action bar get changed.
This looks pretty bad when action bar are changed in a while after swipe is finished.
How can I recreate action bar immediately, before swipe begin?

You can ask android to re-create the actionbar before it automatically does by calling invalidateOptionsMenu();
Do this somewhere close to the point where you change fragments to try and decrease the 'lag' between the fragment and actionbar changing.
Edit
a complete solution may look like this:
class activity extends Activity{
private void switchFragment(){
...do fragment changing stuff
activity.invalidateOptionsMenu();
}
}
class someFragment extends Fragment{
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
//fragment specific menu creation
}
}
whichever fragment is open during the
activity.invalidateOptionsMenu();
will then call its
onCreateOptionsMenu
and you can do fragment specific menu creation in there

It can be done by implementing onCreateOptionsMenu and calling setHasOptionsMenu(true) in the onAttach callback in each fragment and change the actions accordingly.
To show the fragment without any actions setHasOptionsMenu(false) in it

If you are using ActionBar tabs, You would like to see this answer:
How can I change Action Bar actions dynamically?

Finally I couldn't find any sound way to achieve this.
The best would be to make actionbar a part of fragment, not activity, but it's impossible.
I end up with clearing actionbar menu and title when swipe begins(you can set special listener in PageView) and setting menu and title again when swipe complete and new fragment are shown.
In gives some time lag and actionbar looks strangely empty during swipe, but it's best you can do.
Android API is c...

Related

Swipe view with different actionbars

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.

What is the flow like for options menu when we add them in fragment and the main activity?

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.

ActionBarCompat + tabs: remove Fragment Menu Item when switching?

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.

Fragment Specific Actionbar MenuItems

I'm building an application with ActionBarSherlock that uses the Dropdown list navigation style. I have it set that each dropdown list item loads a different fragment, and that works fine. What doesn't work is the menu items in the actionbar. I have setHasOptionsMenu(true) in the fragments that I want to have menu items, as well as
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_menu, menu);
}
for the menus in the fragments. Every time I change fragments, I don't want the menu items appended which is what's happening. When one fragment is selected, the menu loads fine, then a different fragment is selected that isn't supposed to have menu items, and the menu items are the same as the previous fragment. Then if I go back to the first fragment, the menu items get doubled because they keep getting appended. How can I control this?
In the normal case the menu shouldn't be appended. What does your menu.xml look like? Do you have id's set? Maybe creating a menu in the Activity?
I figured it out. I wasn't using FragmentTransaction to load the fragments.

Handling Action Bars with two fragments

I have a layout with two fragments and both fragments have their own action bars, each of which have their own action items and menus. When my app is in landscape mode and both fragments are displayed on the screen, it looks like the framework is choosing to display the action bar on the "right" (or the 2nd fragment), which means the fragment on the left (1st fragment) is missing its action items and menu options.
Everything works fine when the app is in portrait mode, so I'm not sure if I should be doing something to handle the fragments when they are both displayed. Thanks.
EDIT
In each of my fragments I'm using this code to add menu items to the Action Bar:
In fragment 1:
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu_1, menu);
super.onCreateOptionsMenu(menu, inflater);
}
In fragment 2:
#Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu_2, menu);
super.onCreateOptionsMenu(menu, inflater);
}
UPDATE:
Apparently using setRetainInstance(true) is what caused the menus not to refresh. I was using that because I have an AsyncTask that was throwing an exception if the device was rotated. So I fixed one issue, but broke another.
I think you're thinking about this incorrectly. The action bar is not displayed as part of any fragment, but actually as part of the activity. If you declare in your fragments that you provide action items via setHasOptionsMenu(true), then all will be displayed as part of the action bar. You can then take the appropriate action by overriding onOptionsItemSelected(MenuItem item).

Categories

Resources