import android.os.Handler; import android.os.Looper; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.support.v4.app.FragmentActivity; import java.util.HashSet; import java.util.Set; /** * Activity to handle menu in a custom fashion bypassing the framework bug: https://code.google.com/p/android/issues/detail?id=29472 * To be used in conjunction with MenuDelegatorFragment. */ public class MenuManagerActivity extends FragmentActivity { private boolean mOptionMenuCreated; private Set mRegisteredFragments = new HashSet(); private final Handler handler = new Handler(Looper.getMainLooper()); private boolean mInvalidatePosted; public void registerFragmentForOptionMenu(MenuDelegatorFragment fragment) { if (mRegisteredFragments.add(fragment)) { if (mOptionMenuCreated) { postInvalidateOptionsMenu(); } } } public void unregisterFragmentForOptionMenu(MenuDelegatorFragment fragment) { if (mRegisteredFragments.remove(fragment)) { postInvalidateOptionsMenu(); } } /** * Method needed cause subsequents calls of {@link #invalidateOptionsMenu()} on Android pre 4.4 * will get eaten and ignored by the framework. */ private void postInvalidateOptionsMenu() { if (mInvalidatePosted) { return; } mInvalidatePosted = true; handler.post(new Runnable() { @Override public void run() { mInvalidatePosted = false; invalidateOptionsMenu(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { boolean displayMenu = super.onCreateOptionsMenu(menu); final MenuInflater menuInflater = new MenuInflater(this); for (MenuDelegatorFragment f : mRegisteredFragments) { f.onCreateOptionsMenu(menu, menuInflater); } mOptionMenuCreated = true; return displayMenu; } @Override public boolean onPrepareOptionsMenu(Menu menu) { boolean displayMenu = super.onPrepareOptionsMenu(menu); for (MenuDelegatorFragment f : mRegisteredFragments) { f.onPrepareOptionsMenu(menu); } return displayMenu; } @Override public boolean onOptionsItemSelected(MenuItem item) { // this may be weird behavior: I let the call reach both the activity both any single fragment registered for option menu boolean handled = super.onOptionsItemSelected(item); for (MenuDelegatorFragment f : mRegisteredFragments) { handled |= f.onOptionsItemSelected(item); } return handled; } @Override protected void onDestroy() { super.onDestroy(); mRegisteredFragments.clear(); } }