In my app I have one fragment that I add by calling replace() on fragmentTransaction.
This fragment, let´s call it Fragment1, has some menu items that are added to action bar by calling onCreateOptionsMenu and setHasOptionsMenu(true) in onCreate().
From this fragment I then add another fragment that is added by calling add() on FragmentTransaction.
This fragment2 also has options menu but removes options for the first fragment. Then, on API 19 when I click on Back Button, it takes me back to Fragment1 and the options for this menu are added back, since the activity that hosts both of these fragments calls onCreateOptionsMenu and then onPrepare options menu. Also the same methods are called in Fragment1.
When I run my app on API 16, all the mentioned methods are called as well, but either the Menu Items for Fragment1 are not added back at all, or the three-dot-menu-group is added to a wrong place. I assume there is something different in the lower API, maybe even a bug. How should I fix this issue? Anyone with some experience?
This one is what it looks like when going back from the second fragment ot the first one and what it should look like on API 16:
This is how it is supposed to work and what it looks like on API 19 after going back from the second fragment to the first one:
I don´t attach any code because I think it is not relevant for this question. There is just some different behavior in different platforms and I just don´t see what I should do about it. Thanks for any help.
Related
According to the Android menu documentation and a similar question, onPrepareOptionsMenu should be used to update menus dynamically. For Android 3.0 and higher, the documentation says:
When an event occurs and you want to perform a menu update, you must call invalidateOptionsMenu() to request that the system call onPrepareOptionsMenu()
However, when calling invalidateOptionsMenu(), the system calls both, onCreateOptionsMenu() and onPrepareOptionsMenu(). Resuming the activity also either calls both methods (if it was stopped in background) or none.
To me, this sounds like the differentiation between the two methods is obsolete. Is there any situation in which Android only calls onPrepareOptionsMenu() but not onCreateOptionsMenu()? Additionally, is there a way to manually request that Android only calls onPrepareOptionsMenu(), like it is implied in the documentation (cited below)?
[onCreateOptionsMenu()] is only called once, the first time the options menu is displayed. To update the menu every time it is displayed, see onPrepareOptionsMenu(Menu).
Thank you very much!
You are using Activity menu here, so assuming you have single activity app it will be only inflated once, during onCreateOptionsMenu - that's the scenario with a single call.
If you want to change it, then you have to invalidate the current one and inflate a new one - as it's an app's global menu it only make sense if you want to change its contents - you do that using onPrepareOptionsMenu and then inflate it again in onCreateOptionsMenu call.
But if you make lots of menu changes then it amy be better to use to use Fragment specific menus - they only live as long as the their fragment - menus
So to answer your specific question - you cannot NOT trigger the onCreateOptionsMenu. You can override it to do absolutely nothing but then the menu will not be inflated
EDIT - it seems I misunderstood the documentation as well. The key bit for onPrepareOptionsMenu is:
This is called right before the menu is shown, every time it is shown.
Which in practice means that every time you click on the Menu onPrepareOptionsMenu will be called, without calling onCreateOptionsMenu
I'm trying to make an app which has the DrawerActivity as the main activity. I have implemented 8 fragments within it, which correspond to each item in the drawer. Now, the problem I have is, whenever I try to press the back button to go back to the DrawerActivity from the fragment, I end up exiting the app instead. I've been searching on forums for three days now, and have not found any solution to this. Quite frustrated, I stupidly deleted my code, so I can't really show it right now. Can anyone simply explain to me how I should exit a fragment using the back button, and return to my main activity?
Current scenario:
DrawerActivity contains eight fragments, all independent of each other. Let's call them fragments A through H. When I go to fragment A, I should be able to open the navigationDrawer and head to any other fragments from B to H. However, on pressing the back button, I should also be able to go back to the drawer activity's main page.
Things I have tried which didn't work are
1. Using onBackPressed and popBackStack.
2. Creating custom listener.
3. Using fragmentTransaction.
I can't believe how stupid I am. I was using my Gmail app on my phone when I suddenly realized that the first fragment in the drawer activity is always the default fragment, and the app should always revert to it on the back button press. What I was thinking was that the drawer activity would go back to the original state when back is pressed, but I didn't account for the fact that fragments are part of the activity itself.
Thank you all for trying to understand my problem, which wasn't really a problem at all... It seems I learned something in spite of myself.
Have you tried overriding onBackPressed() without calling the superclass method? (So that you prevent finish() from being called.)
#Override
public void onBackPressed() {
//show Fragment A
}
Call it without the "super.onBackPressed()" and it should work.
You must add your fragment to the android back Stack like this:
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.your_container,fragment,fragment.TAG)
.addToBackStack(null)
.commit();
On my app I am using a Main Activity, which has a Navigation Drawer, and as the user go to an options from the drawer, it will change the fragment beging displayed accordingly to the option selected.
If the user hit's "Back button" several times, it will go back to a point in which it will reach my Main Activity, which is a blank and empty layout.
When I reach this point (my main activit, empty), I would like to exit the app, or, open the Navigation Drawer.
The problem is, I don't know any event that shows me that I am back to the Main Activity. I checked the onResume, but it's never called, which makes sense, since the main activity has never been stopped.
I thought perhaps there would be an event from the fragment manager that would be called on the Main Activity when a fragment was detached, and from there I could check if there was no fragment at all attached?
When you push your first fragment, add a tag to it. Something like
transaction.replace( R.id.rootContainer, firstFragment, "rootFragment");
Whenever user presses back button, you can get your rootFragment from FragmentManager
FirstFragment myFragment = (FirstFragment) getSupportFragmentManager().findFragmentByTag("rootFragment");
And check if this fragment is visible or not, by myFragment.isVisible(), if not, then keep popping the stack, if it is visible, it means user is on the first fragment. Now you can either quit the app, or show your menu drawer.
Good night good sir. Thank you for your tip.
I used a different approach, based on your repply, that gave me quite a few insights.
On main activity, I Overrided the onKeyDown and check if it was pressed the Back Button. If yes, then I check the size of my Back Stack.
Uppon that, I decide if I want to finish my application.
Also, thanks for the tip of "labeling" the fragments on the back stack, didn't know I could do that.
My objective is to you use one menu for all activities. For that, I have a base activity which consists of 2 methods: onCreateOptionsMenu() and onOptionsItemSelected(). In onCreateOptionsMenu(), I am creating a menu using MenuInflater.
Further, I have 2 activities which extends the above BaseActivity so that same menu is shown for both the activities. My issue is that, when my first activity is launched, options menu is shown, I move to second activity from the first. In the second activity also, when I press the menu button, I am able to view the menu. After that, using Back key press, I come to first activity again, the menu is also shown up there, But when I move to the second activity thereafter, menu is not shown to me.
Can you please post code of your Base Activity's onOptionsItemSelected and onCreateOptionsMenu?
Anyway, with no code available. And not enough clarity, I assume that the following will work for you...
add #Override
public void onBackPressed() {
finish();
}
to your base activity
Minimum SDK version could be the cause. If you reduce it to 13-, you should probably see the menu show up again. Good article on this subject: POST
In my main activity, I have an actionbar with NAVIGATION_MODE_TABS. The contents of each tab is a listfragment.
I'd like to make it so that that when a listitem is clicked, a new fragment is brought into view, and the actionbar mode is changed to NAVIGATION_MODE_STANDARD (so that the tabs are now hidden).
I've managed to get this to work with the following code:
In the listitemclick method:
ActionBar actionBar = getActivity().getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
Fragment albumListFragment = new AlbumListFragment();
albumListFragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(android.R.id.content, albumListFragment);
ft.addToBackStack(null);
// Commit the transaction
ft.commit();
Log.i("FragmentList", "Item clicked: " + id);
The problem is when I press the back button, the tabs are still gone, and the previous fragment doesn't come back into view.
Am I doing something wrong.. Is it something to do with the fragment backstack? Should I go about it another way, or even override the backpress?
--Edit--
For clarity - I am calling addToBackStack when I call fragmenttransaction.replace, but when I press the back button, the previous fragment is not restored.
Maybe this is a little late, I tried to re-construct your problem for hours but didnot succeed. I tried to switch from a listview in a fragment hosted by a ActionBar Tab to another view by the way described in your question(i.e. ft.replace(android.R.id.content, albumListFragment);) but with no effect. After some google and stackoverflow, I use this way to successfully switch the fragment within the tab, yet with no problem as you have.
As the "action bar is not showing correctly" problem, its probably caused by the backstack revert and UI change as describe in android developer guide. you might try to override the onBackStackChanged() callback and re-construct the UI.
As the "backstack does not bring the previous fragment back" problem, you may want to post a little more code to help others re-construct the problem to find the answer.
Wish helpful.
I experienced exactly the same issue and figured it out that the problem only occurs when you set the ActionBar back to NAVIGATION_MODE_STANDARD.
The only solution for me was to place the new fragment with no tabs in a helper activity which has NAVIGATION_MODE_STANDARD. Then you can easily use the back button functionality provided by Android to go back to the activity with NAVIGATION_MODE_TABS and retain its state.
FragmentTransaction.replace() actually removes the previous fragment in the layout and add new instance of the fragment.
Try using FragmentTransaction#show() and FragmentTransaction#hide() methods instead of replace.
The backstack ends the current activity and goes to the previous activity, not the previous fragment. (See the backstack guide: http://developer.android.com/guide/components/tasks-and-back-stack.html).
You could force, as you suggested, the behavior by overriding onBackPressed, however, I don't know that I would change the natural Android behavior in such a way. If you look at other apps, particularly core apps, that do similar things the back button does not go to a previous fragment, but a previous activity.
Also you do have total control on the behavior of the "up" button (that is your app icon on the action bar with a left arrow). You have to programatically set it up to be used as a button as described in the ActionBar guide (let me know if you need to know how to do this) and with that you could have it set up a previous fragment on a stack that you maintain somewhere.