I'm having trouble getting onPrepareOptionsMenu() to work correctly. No matter what I try, I can't get it to be called.
The architecture of my application is as follows: my main Activity contains a Fragment which holds a ViewPager, which in turn has four child Fragment instances. Currently, I'm (successfully) populating the initial options menu in the Activity with onCreateOptionsMenu(), but I wish to add some extra options corresponding to each active child Fragment.
Within my child Fragments, I've made sure that setHasOptionsMenu(true) is being called in onCreate() and that getSherlockActivity().supportInvalidateOptionsMenu() is called in onActivityCreated(). In the main Activity, onCreateOptionsMenu() is called once after the child Fragments are instantiated, regardless of whether they contain supportInvalidateOptionsMenu() or not. It is subsequently called again whenever the Fragment in the Pager is replaced.
I've tried moving the onPrepareOptionsMenu() code up a level to the parent Fragment and to the main Activity - to no avail, which suggests that the problem is not related to my use of nested Fragments. I've also tried moving the onCreateOptionsMenu() method down from the main Activity to both fragments, where it goes uncalled.
If anyone has any idea what's going on here I'd be very grateful, as I've been stuck on this for two days now.
UPDATE - I've worked out exactly what the problem is now, only I'm still not sure how to fix it. I'm testing on 4.2 and it seems that onCreateOptionsMenu() is called after onResume() in the Activity - as seen in onCreateOptionsMenu called after onResume on JB 4.2. I assume this means that fragments can't call onPrepareOptionsMenu() because the menu doesn't even exist until after they're instantiated. So how do I solve this?
It was, somewhat inevitably, an issue with ActionBarSherlock that I'd overlooked when checking its issues page on github. Basically, the functionality for options menus in nested fragments has not yet been added, see: https://github.com/JakeWharton/ActionBarSherlock/issues/828. My solution for now is to replace Watson.java with one of the modified files in the comments.
Related
Scenario:
I using a ViewPager inside a Fragment. This ViewPager inflates 3 fragments (AFragment, BFragment, CFragment) pages using FragmentPagerAdapter.
I have printed logs inside
onCreateOptionsMenu
onPrepareOptionsMenu
of all 3 fragments.
Problem:
For AFragment when created onCreateOptionsMenu was called only once,
but when I swiped to BFragment onCreateOptionsMenu and
onPrepareOptionsMenu for BFragment were called twice. And similar
thing happened with CFragment.
Can anyone explain why this is happening and How I can avoid it?
Thanks.
Because android by defaults loads a next and previous fragment in background, in order to load fragments efficiently and to remove lag.
However you can customise the same by using setOffscreenPageLimit (int limit), Which is used to set the number of extra fragments you would like to load in background. By default its set to 1.
Read Android fragments strange load for more information
I am implementing Tab Layout with Swipeable Views in android. For implementation I had followed
AndroidHive
and
Tabs and swipe views.
But with both, I am facing the same problem. I am having 3 fragments but when my application run, onCreateView of 1st and 2nd Fragment called instead of only of 1st fragment's. When I swipe and go to 2nd fragment, onCreateView of 3rd Fragments get called.
So, whatever I code in 2nd fragment execute in the first fragment view. I researched and came to know that it happen to keep the next fragment into memory for smooth animation. But I am wondering, where I would code in the fragment so that it will execute only once or how to restrict Fragment getItem() method to be called only once. What can be the solution for this?
According to the Fragment's documentation you can implement the onCreate() link:
The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
This should fix your problem, because i guess you now only use the onCreateView which might be called more than once.
For more information you can check the Fragment's lifecycle or documentation
I have some slight issues with my menu items for my fragments. I have an overarching activity that hosts the fragments. I'm unsure whether I should have my menu options code in every single fragment and not the activity or simply just the activity? What is better practice and what works best? One of my menu items is also affected by OnActivityResult and therefore that menu item doesn't work unless that method is posted into every fragment as well. This just seems like a lot of duplicated code. I would simply put everything in the main activity but that seems like bad practice and surely the main activity should have minimal code and the fragments should hold their own separate code. I need to use the OnCreateView method in my fragments in order to refresh an image adapter because the ViewGroup needs to be accessed. I'm just wondering what people's opinions are and what is best for simplicity of my code?
Thanks in advance.
It is alright to put your menu item in the activity's menu list when it semantically belongs to the activity, such as logging in and out. You can just start up some other activity with startActivityForResult and change the status of the menu item according to the result of onActivityResult.
In addition, fragments can also have onActivityResult method, so if you can separate the logic of startActivityForResult and onActivityResult into one of your fragments, it might be a good idea to do everything in that fragment.
I am using the Sherlock ActionBar library and I have a SherlockFragmentActivity implementing ActionBar.TabListener (for my tabs) and I have 3 tabs...each being a SherlockFragment. When I rotate, the entire Activity is recreated and I lose all variables declared in my onCreate within the Fragment. How would I go about fixing this?
I figured I should be using fragments as tabs instead of activities...is this wrong?
EDIT: I should mention that my current workaround is to have static Lists in the Tab Activity and have the fragment push stuff to those lists on onPause (and get stuff back from them on onResume). I REALLY don't like doing this and I know there has to be a better way.
Also, regarding if(savedInstanceState==null), I've tried that and it doesn't seem to work. I think it's because the Activity that holds my Fragments is being recreated and the tabs need to be recreated.
There's a method called setRetainInstance() in the Fragment class, that you need to set to true. That'll save the instance of your fragments, and you can then check for any saved instances in onCreate().
More info available here:
http://developer.android.com/reference/android/app/Fragment.html
I use ActionBarSherlock compatibility library and experience a strange behavior when paging between tabs of Action Bar. Each tab contains a simple Fragment, nothing special. I observed that fragment's onCreateView method is called too often even though there is no screen orientation change. It looks like some kind of pre-caching. I have three tabs there, when the activity is created, the onCreateView is called only for the first two fragments. The last fragment doesn't create view until I page one step forward. The same behavior occurs when paging from the last tab to the first.
Has anybody any idea why this occurs? I would assume creating all views at once, when the parent activity finishes its creating. I don't want to create views again and again, there are no changes in the fragments, they are static. It has no sense and causes paging to be sluggish a bit...
After a few hours I found what's happening there. ViewPager has a default setting DEFAULT_OFFSCREEN_PAGES which sets the maximum number of views (fragments in my case) to be stored in the view container of ViewPager. It is obviously some kind of resource optimization; invisible views can be thrown away and restored when needed.
There is nothing easier then change this value by setOffscreenPageLimit(int limit) setter which I overlooked.
I think it was done consciously to increase user experience.
The same way ViewPager from compatibility lib is implemented.
Anyway, sources are available.