The is a problem that affects platforms prior to 3.0, i.e. when Sherlock acts as a proxy to provide the action bar menu items.
I have a Fragment Activity that contains two fragments, each with its own set of options menus. When the activity starts the first fragment tab is shown and its menu items work normally. However, the first time that I switch to the other tab its menu items do not respond. If I switch back to the first tab and select the other tab again they start to fire normally.
It looks like this is a known problem. Check out the discussion here.
My workaround for now is to detect the first time that the second tab is selected and programatically switch back to the first tab. This forces the user to select the second tab again, but from that point on it works normally, as long as the user stays in that activity.
I am wondering if anyone else has found a more elegant solution to this problem. Thanks!
First fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
moveMenuItem = menu.add(Flashum.MENU_GROUP_MULTI, Flashum.MOVE_FLASHES_ID, 0, R.string.move_flashes);
cloneMenuItem = menu.add(Flashum.MENU_GROUP_MULTI, Flashum.CLONE_FLASHES_ID, 0, R.string.clone_flashes);
deleteMenuItem = menu.add(Flashum.MENU_GROUP_MULTI, Flashum.DELETE_FLASHES_ID, 0, R.string.delete_flashes);
moveMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
moveMenuItem.setIcon(R.drawable.move2red);
cloneMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
cloneMenuItem.setIcon(R.drawable.hard_drive_clone);
deleteMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
deleteMenuItem.setIcon(R.drawable.delete);
}
Second fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
saveMenuItem = menu.add(Flashum.MENU_GROUP_SAVE, Flashum.SAVE_CHANGES_ID, 0, R.string.save_changes);
saveMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
saveMenuItem.setIcon(R.drawable.save);
menu.setGroupVisible(Flashum.MENU_GROUP_SAVE, true);
recMenuItem = menu.add(Flashum.MENU_GROUP_REC, Flashum.RECORD_ID, 0, R.string.record);
recMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
recMenuItem.setIcon(R.drawable.microphonehot);
}
Try to clear your menu before you inflate it in your fragments. So in your fragments in onCreateOptionsMenu methods call menu.clear(); at the beginning and then inflate your menu.
Something like this:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
saveMenuItem = menu.add(Flashum.MENU_GROUP_SAVE, Flashum.SAVE_CHANGES_ID, 0, R.string.save_changes);
saveMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
saveMenuItem.setIcon(R.drawable.save);
menu.setGroupVisible(Flashum.MENU_GROUP_SAVE, true);
recMenuItem = menu.add(Flashum.MENU_GROUP_REC, Flashum.RECORD_ID, 0, R.string.record);
recMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
recMenuItem.setIcon(R.drawable.microphonehot);
}
Try it in both of your fragments.
Instead of detecting when the second tab is selected, switch the fragments programmatically in the onCreate of your Activity using a post delayed method. For example I have 3 fragments and I switch them in reverse order (2, 1, 0) and it fools your users with a nice animation at the beginning of the Activity:
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB){
mIndicator.setCurrentItem(2);
mIndicator.postDelayed(new Runnable() {
public void run() {
mIndicator.setCurrentItem(1);
mIndicator.postDelayed(new Runnable() {
public void run() {
mIndicator.setCurrentItem(0);
}}, 100);
}}, 100);
}
Related
I'm currently having an issue with the menu bar, it will work 75% of the time, but after a while it will start to drop off the Shown items and won't add them or any others back onto the visible items (It will still add to the hidden items)
This is what its meant to look like
(Main Screen)
(ViewPager Fragment
)
And it looks fine most of the time, but after a while the visible items drop off and don't come back (When moving between fragment on the viewPager i clear and inflate the menu, but i've removed this and the issue still occurs)
(Main Screen)
(ViewPager Fragment)
The items inside the Elapsed icon at the end all generate fine and get added as they're meant to, its just the ones that're meant to be visible that aren't showing
This is the ViewPager onCreateOptionsMenu function
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
// Clear Sync and Settings menu
menu.clear()
// Inflate the options menu from ViewModel
inflater.inflate(viewModel?.getMenuLayout() ?: R.menu.job_details_menu, menu)
// Let the VM handle the creation
viewModel?.onCreateOptionsMenu(menu)
super.onCreateOptionsMenu(menu, inflater)
}
I have tried placing the super call at the start and end, it hasn't made a difference.
This is the Main Menu function
#Override
public void onCreateOptionsMenu(#NonNull Menu menu,#NonNull MenuInflater inflater) {
// Add the Schedule Search
final MenuItem item = menu.add(App.getAppContext().getString(R.string.search_hint));
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
SearchView sv = new SearchView(getActivity().getSupportActionBar().getThemedContext());
sv.setOnQueryTextListener(this);
sv.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean queryTextFocused) {
if (!queryTextFocused) {
item.collapseActionView();
}
}
});
item.setActionView(sv);
super.onCreateOptionsMenu(menu, inflater);
}
Why would this be not refreshing correctly? (Mostly the ViewPager Fragment)
Change:
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
To
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
I displayed a fragment A that implements a ViewPager with several fragments (nested fragments).
In my nested fragments, I inflate a menu with the following method.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.my_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
This question was already asked here. And i tried all the answers its not working.
My issue is
Everything working fine.but when i open another fragment(it have not any option menu) and get back to previous view pager fragment while clicking menu item onOptionsItemSelected not firing. When i swipe fragment in viewpager and come back to the previous one, when i click menu item its firing.
Its because viewpager maintain 3 fragment alive at a time. so when you come back, it set menu visibility status true to last fragment. thats why your menu item click not firing.
Use the following in the fragment where you keeping a viewpager in your case fragment A.
private boolean isInitial=true;
#Override
public void onResume() {
super.onResume();
if (!isInitial) {
int pos = viewpager.getCurrentItem();
if (pageAdapter.getItem(pos).getUserVisibleHint() && pageAdapter.getItem(pos).isVisible()) {
pageAdapter.getItem(pos).setMenuVisibility(true);
}
} else {
isInitial = false;
}
}
I've got three fragments in a viewpager.
Two of these fragments have their own version of the onCreateOptionsMenu method:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Set up 1 action button
inflater.inflate(R.menu.home_snapshot_add, menu);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Set up 2 action buttons
inflater.inflate(R.menu.home_snapshot_send, menu);
}
The home activity has a basic onCreateOptionsMenu method:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return false;
}
In the onCreate method, each fragment calls the method:
setHasOptionsMenu(true);
Each of the menu items have the tag:
android:showAsAction="always"
Seems like as I open the Activity, all three buttons appear.
However, when I scroll through them, the wrong ones magically disappear.
It feels like the activity is calling every Fragment's options menu on Activity creation and then changes the menu appropriately when I swipe left and right.
I've checked the menus but not sure what's wrong.
Anything you reckon I need to check? I'm a little out of ideas.
Thanks!
In your ViewPager's OnPageChangeListener and after setting the adapter to the ViewPager, have this:
#Override
public void onPageSelected(int position){
invalidateFragmentMenus(position);
}
private void invalidateFragmentMenus(int position){
for(int i = 0; i < mViewPagerFragentAdapter.getCount(); i++){
mViewPagerAdapter.getItem(i).setHasOptionsMenu(i == position);
}
invalidateOptionsMenu(); //or respectively its support method.
}
After setting your fragment adapter call the same method with following argument:
invalidateFragmentMenus(mViewPager.getCurrentItem());
The above statements will prevent all other fragments not to receive call on onCreateOptionsMenu() method when invalidateOptionsMenu() is called, only the currently visible fragment will receive and be able to populate the options menu.
I've used this and it has worked for me:
//In your Fragment
#Override
public void onResume() {
super.onResume();
setHasOptionsMenu(isVisible());
}
I am implementing ABS within my application, and I have a FragmentPagerAdapter that allows the user to swipe/select different tabs.
Each of these tabs contains a different fragment. Basically, my problem is that on an Android 2.3.6 device that I'm testing with, when the activity is first called, the first tab-fragment doesn't inflate the menu it is supposed to. However, once I swipe to another tab and go back, it appears.
Here is the code within the fragment:
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
MenuInflater inflater = getSherlockActivity().getSupportMenuInflater();
inflater.inflate(R.menu.menu_ongoing_fragment, menu);
}
Meanwhile, it works completely fine on an Android 4.2 device (the menu is inflated the first time the activity is launched) Does it have something to do with the order in which these two devices are calling the methods?
It's not working because of this:
menu.clear();
Remove that.
You should have the following code on your fragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
};
and instead of "onPrepareOptionsMenu()" use this:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_ongoing_fragment, menu);
super.onCreateOptionsMenu(menu, inflater);
}
I hope this solves your problem!
In Android, I create my menu item like this?
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Menu1");
menu.add(0, 1, 0, "Menu2");
return true;
}
How can I set all the menu item disabled programmatically (in another part of the code in my activity, not in onCreateOptionsMenu() method itself)?
You can use the groupId you set to disable/enable all the menu items at once, using menu.setGroupEnabled(). So for example, since you added the items to group 0, you'd do:
menu.setGroupEnabled(0, false);
Also, if you want to dynamically modify the menu, you should hook into onPrepareOptionsMenu(). onCreateOptionsMenu() is only called once per Activity, so it's good for setting up the initial menu structure, but onPrepareOptionsMenu() should be used to enable/disable menus as necessary later in the Activity.
add returns a MenuItem (which you can also retrieve from the Menu object), that you can store away into a variable.
MenuItem menu1;
public boolean onCreateOptionsMenu(Menu menu) {
menu1 = menu.add(0, 0, 0, "Menu1");
}
public void someOtherMethod() {
if(menu1 != null) {
// if it's null, options menu hasn't been created, so nevermind
menu1.setEnabled(false);
}
}
I prefer to hide them completely if they should not be used (instead of disabling them).
For that I do:
menu.clear();
and to recreate it:
invalidateOptionsMenu();
This also works for menu items added from fragments.
If still relevant:
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
for(int i=0; i<menu.size(); i++){
menu.getItem(i).setEnabled(isMenuEnabled);
}
}
and call invalidateOptionsMenu() then isMenuEnabled changed
If you have multiple occasions where you want to do something with all items of a menu (for example changing the 'checked' state) there is an elegant solution using Kotlin Extension Properties:
(Building on top of the answer of Valery)
In one place define the property 'items' of android.view.Menu:
import android.view.Menu
import android.view.MenuItem
val Menu.items: List<MenuItem>
get() {
val items = mutableListOf<MenuItem>()
for (i in 0 until this.size()) {
items.add(this.getItem(i))
}
return items
}
Now you can use it on any menu:
anyMenu.items.forEach { it.isEnabled = false }