onCreateOptionsMenu() in fragment not replacing ActionBar menus
I'm using the NavigationDrawer in my app and replace the fragment when clicking a item in the drawer. My problem I have is that the menu items in the ActionBar are not updated when I change the fragment.
I've followed this tutorial https://www.grokkingandroid.com/adding-action-items-from-within-fragments/ closely but it's still not working in my app.
Adding some code snippets of the parent activity and one of the Fragments here. What I need is to display the other menu items of the contact form fragment (R.menu.contactform_send_menu) when the initial fragment gets replaced with ContactFormFragment.java.
public class MainActivity extends FragmentActivity implements ActionBar.OnNavigationListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle(R.string.app_name);
// Set up the action bar to show a dropdown list.
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
createNavigationDrawer(savedInstanceState);
}
private final int DRAWER_MAIN = 0;
private final int DRAWER_CONTACT = 5;
// update the main content by replacing fragments
private void selectItem(int position) {
Fragment fragment = null;
Bundle args = new Bundle();
boolean isFragment = false;
switch (position) {
case DRAWER_MAIN:
fragment = new WelcomeSectionFragment();
args.putString(WelcomeSectionFragment.ITEM_NAME, dataList.get(position).getItemName());
args.putInt(WelcomeSectionFragment.IMAGE_RESOURCE_ID, dataList.get(position).getImgResID());
getActionBar().setTitle(R.string.app_name);
isFragment = true;
break;
case DRAWER_CONTACT:
fragment = new ContactFormFragment();
args.putString(ContactFormFragment.ITEM_NAME, dataList.get(position).getItemName());
args.putInt(ContactFormFragment.IMAGE_RESOURCE_ID, dataList.get(position).getImgResID());
getActionBar().setTitle(R.string.contactform_title);
isFragment = true;
break;
default:
break;
}
if (isFragment) {
fragment.setArguments(args);
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
setTitle(dataList.get(position).getItemName());
mDrawerLayout.closeDrawer(mDrawerList);
}
}
}
and the fragment:
public class ContactFormFragment extends Fragment {
public ContactFormFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ca = getActivity();
Reachability.registerReachability(ca.getApplicationContext());
settings = ca.getSharedPreferences(Konstanten.PREFERENCES_FILE, 0);
member = new Gson().fromJson(settings.getString(Konstanten.MEMBER_OBJECT, null), Member.class);
latoFontLight = Tools.getFont(ca.getAssets(), "Lato-Light.ttf");
latoFontBold = Tools.getFont(ca.getAssets(), "Lato-Bold.ttf");
// Update action bar menu items?
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Do something that differs the Activity's menu here
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
if (Build.VERSION.SDK_INT >= 11) {
// selectMenu(menu);
inflater.inflate(R.menu.contactform_send_menu, menu);
}
}
}
When debugging I can see that setHasOptionsMenu(true); gets called in onCreate() and I also get into the onCreateOptionsMenu() of ContactFormFragment.java. I just don't understand why the action bar keeps its initial menu items and doesn't replace them. What am I missing?
Thanks for any help.
Try putting setHasOptionsMenu(true);
inside the onCreateView()
of your ChildFragment.java
I don't see one in the code you posted.
I got it working! The problem I had was that I added a custom drop down menu to the main fragment. So each time I change the fragment through the drawer navigation I manually have to remove that drop down menu and when returning to the main fragment I will re-add it.
Here is what I did:
In the parent activity:
MainActivity.java:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.signin_menu, menu);
getMenuInflater().inflate(R.menu.clear_search_history_menu, menu);
// Search
// Associate searchable configuration with the SearchView
getMenuInflater().inflate(R.menu.search_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
getMenuInflater().inflate(R.menu.signin_menu, menu);
getMenuInflater().inflate(R.menu.clear_search_history_menu, menu);
// Search
// Associate searchable configuration with the SearchView
getMenuInflater().inflate(R.menu.search_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.search).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
// This is the selection of the drawer (stripped some code to keep it short)
private void selectItem(int position) {
Fragment fragment = null;
Bundle args = new Bundle();
boolean isFragment = false;
ActionBar actionBar = getActionBar();
switch (position) {
case DRAWER_MAIN:
fragment = new WelcomeSectionFragment();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setListNavigationCallbacks(new GameSystemsAdapter(getActionBarThemedContextCompat(), allSystemsPlusEmpty), this);
actionBar.setTitle(R.string.app_name);
isFragment = true;
break;
case DRAWER_FAVORITES:
fragment = new FavoritesMainFragment();
// Remove System-Select Drop-Down
actionBar.setListNavigationCallbacks(null, null);
actionBar.setNavigationMode(0);
actionBar.setTitle(R.string.favorites);
isFragment = true;
break;
case DRAWER_TOP_MEMBERS:
fragment = new TopMembersFragment();
// Remove System-Select Drop-Down
actionBar.setListNavigationCallbacks(null, null);
actionBar.setNavigationMode(0);
actionBar.setTitle(R.string.top_members_top_helping);
isFragment = true;
break;
default:
break;
}
if (isFragment) {
fragment.setArguments(args);
FragmentManager frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
setTitle(dataList.get(position).getItemName());
mDrawerLayout.closeDrawer(mDrawerList);
}
}
and here the part of the fragment(s):
ChildFragment.java
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (Build.VERSION.SDK_INT >= 11) {
selectMenu(menu);
}
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
selectMenu(menu);
}
private void selectMenu(Menu menu) {
parentActivity.getMenuInflater().inflate(R.menu.contactform_send_menu, menu);
}
If there are any better solutions I'm very interested in your ideas.
There are two cases to consider:
Let's begin with option 2 since it's the most common case.
If you have fragment specific items and global items at the same time, you do not want to use onCreateOptionsMenu()
within the fragment. The reason is that it would look weird - even if it worked. The fragment actions would be added right after creating the fragment, while the global items would be added after the drawer has closed (by default). I think no user would like that.
What you could do to still let the fragment decide which items to display is to create an interface for all fragments to implement. This could define one method which would return the menu id for the menu to inflate or -1
if no menu should be inflated.
In case of option 1, I can only assume that you clear()
the menu within the Activity's onCreateOptionsMenu()
. Otherwise it wouldn't delete the fragments' menu entries. So just get rid of the clear()
and all should be fine.
上一篇: 方向更改android后隐藏打开的菜单