I am trying to show a button in the actionbar when a Fragment is shown and to hide the button when the other Fragment are shown.
I Override the onCreateOptionsMenu method:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
MenuItem item= menu.findItem(R.id.action_example);
item.setVisible(true);
super.onCreateOptionsMenu(menu,inflater);
}
And use setHasOptionMenu(true):
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
I have done a test and I noticed that initially the button doesn't appear in the other Fragment , but after I open the Fragment in which I put this code above, the button is shown also in the other Fragment.
What you are missing is removing the optionsMenu in the onDestroy of the fragment. The behaviour you describe is logical with your code: when the Fragment is created you also create the options menu. It will not automatically be destroyed when the Fragment is destroyed.
Related
I have multiple fragments in my app. I want to add search function to may app. When i add search view in toolbar, the listener is in MainActivity. The problem is when i submit the query, the action for every fragment is same. Can i differentiate the action for every fragment ?
How to do that?
First of all, I guess you have added the SearchView in Activity through menu.
If so then you can implement the menu inside each fragment instead of Activity. Then you can get Search functionality for each fragment.
To enable Option Menu for fragment you have to override onCreate like below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
Then you have to inflate your menu in
onCreateOptionsMenu like below:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Add your menu entries here
super.onCreateOptionsMenu(menu, inflater);
}
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 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'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 have a problem with FragmentStatePageAdapter (that I use as adapter for a ViewPager) and the menu items from the action bar.
When I launch the application, everything is fine. If I move the task to background (for example, pressing HOME button) and I start doing stuff until the activity is ended, then when I go back to my application (through the launcher or a notification I create) everything is fine except there are duplicated menu items in the action bar.
An important detail is that the only duplicated items are those that are created in the onCreateOptionsMenu() of each fragment I use in the ViewPager.
If I replaceFragmentStatePageAdapter with FragmentPageAdapter the items are not duplicated anymore, but the fragments are not shown in the ViewPager (getItem() function from the adapter is never called so it does not return any fragment).
Any ideas? A way to avoid FragmentStatePageAdapter to duplicate menu items? Maybe use FragmentPageAdapter but with a modification to show the fragments? A modification in my fragments?
Here are some code snippets from my application...
How menu items are created inside the fragments:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
/* Create play button */
final MenuItem mPlay = menu.add(R.string.play_all);
mPlay.setIcon(R.drawable.ic_play_all);
mPlay.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mPlay.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
final List<Song> songs = getSongs();
if (songs.size() == 0) {
/* Show message */
Toast.makeText(mContext, R.string.no_song_list, Toast.LENGTH_LONG).show();
} else {
/* Play song list */
try { PlayManager.getService().playList(songs); } catch (Exception e) {}
}
return false;
}
});
/* Create menu */
super.onCreateOptionsMenu(menu, inflater);
}
How fragments are instantiated in the ViewPager adapter
#Override
public Fragment getItem(int position) {
final Class<?> cls = mTabs.get(position);
/* No tab */
if (cls == null)
return null;
/* Instantiate fragment */
final Fragment fragment = Fragment.instantiate(mContext, cls.getName(), null);
/* Add to list */
mFragments.put(position, fragment);
/* Return fragment */
return fragment;
}
Thanks!
PS: I tried to change the launchMode of the activity to "singleTop" and I also tried to return in getItem() the previosly created fragment (but that's useless as getItem() is never called when I return to the application, as I said before).
I found a solution to my problem a few days after posting my problem. I'm sorry for putting it here so late.
The following code fixed my problem:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.remove("android:support:fragments");
}
As simple as writing that piece of code in the activity where I instantiate and use the fragments.
I hope this helps :)
Before inflating the options menu in your Fragment inside the ViewPager, check whether the Fragment instance is visible to prevent duplicated menu items:
// This should be in your Fragment implementation
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
if(isVisible())
{
inflater.inflate(R.menu.menu_fragment, menu);
}
super.onCreateOptionsMenu(menu, inflater);
}
I assume the problem is that the FragmentStatePagerAdapter creates a new Fragment each time you swipe. As a result, onCreateOptionsMenu() is called for each Fragment that is created.
There are, I think, two solutions:
Take the action bar manipulation out of the Fragments. Instead of setting an onclick for the menu item inside of the Fragment, you send a message to the current Fragment from the Activity.
Use Menu.findItem() to see if another Fragment has already added the MenuItem you want, and if so attach the current Fragment to it (in onPrepareOptionsMenu()).
I found some solution try it may be work
In your duplicate menu fragment
Add menu.clear() before inflate menu file in onCreateOptionsMenu(Menu menu, MenuInflater inflater)
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.main,menu);
}