I am using drawerlayout in activity with several fragments. By clicking the navigation item, I switch the fragment this way:
switch (index) {
case 0:
if (checkinFragment == null) {
checkinFragment = new CheckinFragment();
ft.add(R.id.main_container, checkinFragment, "0");
} else {
ft.show(checkinFragment);
}
break;
case 3:
if (jianGuanFragment == null) {
jianGuanFragment = new JianGuanFragment();
ft.add(R.id.main_container, jianGuanFragment, "3");
} else {
ft.show(jianGuanFragment);
}
break;
}
ft.commitAllowingStateLoss();
Each fragment has a different menu resource file inflated in its onCreateOptionsMenu(Menu menu, MenuInflater inflater) method.
Steps:
1. When first enter the activity the menu in checkinFragment is shown.(All right)
2. Then switch to the jianGuanFragment, the menu in jianGuanFragment is shown.(Also right)
3. However, when switch back to the first fragment(checkinFragment), the actionbar menu isn't updated. The showing menu is still the one in jianGuanFragment. That's the problem.
And from the log I know the onCreateOptionsMenu in the showing fragment is called each time I switch to it. That's to say:
onCreateOptionsMenu is called but actionbar menu isn't updated.
Anyone can help me? Thanks a lot.
EDIT 1: add the code in onCreateOptionsMenu:
(1)in checkinFragment
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
LogUtils.e("TAG", "CheckinFragment onCreateOptionsMenu");
menu.clear();
inflater.inflate(R.menu.menu_setting, menu);
}
(2)in jianGuanFragment
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
LogUtils.e("TAG", "JianGuanFragment onCreateOptionsMenu");
menu.clear();
inflater.inflate(R.menu.menu_jianguan, menu);
}
EDIT 2: I use toolbar, not the old actionbar.
At last I find the solution:
Each time entering a fragment, re-set the toolbar as ationbar again.
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
AppCompatActivity compatActivity = (AppCompatActivity) mActivity;
mToolbar = (Toolbar) compatActivity.findViewById(toolbarId);
compatActivity.setSupportActionBar(mToolbar);
}
}
Try this
1)in checkinFragment
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
LogUtils.e("TAG", "CheckinFragment onCreateOptionsMenu");
getActivity().getMenuInflater().inflate(R.menu.menu_setting, menu);
super.onPrepareOptionsMenu(menu);
}
Use invalidateOptionsMenu(). You need to use it where call to OnCreateOptionsMenu() is required.
EDIT:
getActivity().invalidateOptionsMenu() can be used if you want to call it from Fragment.
Hope that helps!!!
Related
I have an Activity with a Toolbar that I set as the supportActionBar. From this Activity I have various Fragments each with a customized ActionBar. I am able to call menu.clear() to remove the existing Menu but I am however unable to add another Menu in the same Fragment. This seems strange because menu.clear() behaves just as I would expect, but when calling inflater.inflate(R.menu.my_custom_menu,menu); appears to do nothing.
Example Fragment where I wish to modify the supportActionBar:
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar();
mGroupViewModel =
ViewModelProviders.of(requireActivity()).get(GroupsViewModel.class);
}
...
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
//Inflating seems to do nothing.
Log.i(TAG,"IN THE ONCREATEOPTIONSMENU FOR FRAGMENT.");
inflater.inflate(R.menu.group_edit_toolbar,menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
Log.i(TAG,"ONPREPARE OPTIONS MENU IN FRAGMENT.");
menu.clear();
super.onPrepareOptionsMenu(menu);
}
Clearly there is something I don't understand but I can't narrow down on what that problem is.
Would a better approach be to have each Fragment have their own Toolbar instead of all my fragments modifying the hosting activity's supportActionBar?
UPDATE
After further testing, I notice that if I try to assign a local MenuItem in my Fragment, I receive a null pointer exception unless I first inflate a menu in the Fragment itself. This is leading me to think that I am not hijacking control of the Activity's supportActionBar in the Fragment, but rather am trying to create a separate ActionBar for the Fragment. Would anyone be able to supplement my thinking here?
Fragment's menu callbacks:
MenuItem editItem;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.i(TAG,"IN ONCREATEOPTIONS");
menu.clear();
//MUST INFLATE MENU OTHERWISE WE GET NULL ERROR.
inflater.inflate(R.menu.home_actionbar,menu);
editItem = menu.findItem(R.id.action_edit_group);
Log.i(TAG,"edititem: "+editItem.getItemId());
super.onCreateOptionsMenu(menu, inflater);
}
// This is called every time the Menu opens.
#Override
public void onPrepareOptionsMenu(Menu menu) {
Log.i(TAG,"IN THE on prepare FOR FRAGMENT.");
menu.findItem(R.id.action_create_group).setVisible(false);
menu.findItem(R.id.action_create_group).setEnabled(false);
if(owner.equals(currUser)){
menu.findItem(R.id.action_edit_group).setEnabled(true);
menu.findItem(R.id.action_edit_group).setVisible(true);
} else {
menu.findItem(R.id.action_edit_group).setVisible(false);
menu.findItem(R.id.action_edit_group).setEnabled(false);
}
super.onPrepareOptionsMenu(menu);
}
onPrepareOptionsMenu is always called after onCreateOptionsMenu and there you're deleting your recently inflated menu!
Just delete onPrepareOptionsMenu and it should work fine.
I have menuItem in fragment A, the menuItem.setIcon work fine the first time, but when I Add fragment B (not replace) and go back to fragment A, the menuItem.setIcon is not working anymore!
here is my code on fragment A, the buttonClicked method work perfectly before I add the fragment B and go back to fragment A
private MenuItem menuItem;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
menuItem = menu.findItem(R.id.action_item);
super.onCreateOptionsMenu(menu, inflater);
}
public void buttonClicked() {
if (condition)
menuItem.setIcon(getResources().getDrawable(R.drawable.ic_action));
else
menuItem.setIcon(getResources().getDrawable(R.drawable.ic_action_checked));
}
you need to call Activity.invalidateOptionsMenu(); to make any menu changes.
I tried so many answers provided by various posts here but nothing worked for me.
Problem- I have navigation drawer that has 6 fragments but single activity. Everything worked fine till I changed 1st ranked fragment in drawer. I wanted Swipe tabs inside first fragment. So I used FragmentStatePagerAdapter.
Each fragment has its own menu along with MainActivity Menu.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Notify the system to allow an options menu for this fragment.
setHasOptionsMenu(true);
}
And inflated like this:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.story, menu);
}
Everything works fine. But When I visit other fragments in navigation drawer then it shows duplicate menu in toolbar. It creates more duplicates if there is space left in toolbar when I visit other fragments.
Try 1 : To solve this problem I initially used:
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.story, menu);
}
With this I don't get duplicate menu but now I don't see MainActivity menus.
Try 2:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
getActivity().invalidateOptionsMenu();
inflater.inflate(R.menu.story, menu);
}
With this I get both Fragment and Activity menu but Duplicates are there.
This should be easy to solve but I am not picking up a way to deal with this. Maybe I didn't understand the life cycle well?
My other approach- Implementing all menus in Fragments will do the trick but this should be our last option.
Solution to this - To maintain both Menu all I have to do is this (Very easy solution):
menu.clear();
inflater.inflate(R.menu.story, menu);
getActivity().getMenuInflater().inflate(R.menu.main, menu);
Problem 2 OnOptionsItemSelected method from 1st fragment is getting called in other fragments.
private void hideAllMenuItems() {
if (actionBarMenu != null) {
actionBarMenu.findItem(R.id.action_item1).setVisible(false);
actionBarMenu.findItem(R.id.action_item2).setVisible(false);
}
}
private void showMenuIcon() {
if (actionBarMenu != null) {
hideAllMenuItems();
if (currentFragment instanceof Fragment1)
actionBarMenu.findItem(R.id.action_item1).setVisible(true);
else if (currentFragment instanceof Fragment2)
actionBarMenu.findItem(R.id.action_item2).setVisible(true);
}
}
call shoeMenuIcon() each time new fragment load..
Hope you are looking for this
I have MainActivity and it's have fragment. I added toolbar from MainActivity;
MainActivity
private Toolbar mToolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mToolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
When I was open any fragment from MainActivity then that fragment use own menu file
In fragment
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.custom_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
As you can see above I inflated custom menu in onCreateOptionsMenu. But It doesn't work.
after
toolbar.getMenu().clear();
add toolbar.inflateMenu(R.menu.menu_blank);
and I am not set toolbar as acionbar,Maybe you should user getActionbar to do something.
I'm not entirely sure this is what you're asking but I think you want to be able to change the options in the menu, dynamically. You can do the following
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
if (mHideSomething) {
MenuItem myItem = menu.findItem(R.id.action_something);
myItem.setVisible(false);
} //otherwise it will show as usual
return true;
}
Then when you want to change something in the menu...
mHideSomething = true;
supportInvalidateOptionsMenu();
EDIT
Now I understand you're just adding odd behaviour when overriding. You can still do the following (although it seems like these items just shouldn't be part of main menu if they're not relevant always)
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.custom_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem mainMenuItemToRemove = menu.findItem(R.id.action_something);
mainMenuItemToRemove .setVisible(false);
}
The only problem with the above is it makes assumptions about what is available in the main menu even though the fragment should be reusable. A better solution would be to pass in an interface to the fragment to call back to the activity and let the activity have control. Better still, update the activity logic and never inflate the main menu at all if not required.
I need to remove the inflated menu after I return to Fragment 1 from Fragment 2 after some action.
I clear the menu after I make the popBackStack, but nevertheless the menu item can't be deleted.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
if (savedItemsExist())
inflater.inflate(R.menu.menu_saved_filters, menu);
else
{
Log.i(TAG + " onCreateOptionsMenu", " going to delete");
menu.clear();
}
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
if (savedItemsExist())
getActivity().getMenuInflater().inflate(R.menu.menu_saved_filters, menu);
else{
menu.clear();
}
super.onPrepareOptionsMenu(menu);
}
If you have menu items tied to a Fragment's lifecycle, you should instead use setHasOptionsMenu(true) on your Fragment and then override onCreateOptionsMenu() in the Fragment, inflating your fragment's menu.
Maybe that is hack solution, but issue solved by replacing the Fragment 2 by Fragment 1 instead of popBackStack()