OptionsMenu appears in double - android

I Have a Fragment inside an Activity. This Activity contains OptionsMenu.
I use a FragmentTransaction to launch a new instance of the same Fragment class, when I selected the OptionsMenu, it appears in double because it load twice.
How can I do to manage OptionsMenu between the Fragments
Thanks.
PS : Sorry for the English

There is no way such way. You can handle on BackPressed and show your own custom menu as a new fragmnet. Or manage your options menu inside of FragmentTransaction inactivity in dependent of your fragment class and content

I find a solution,
I create the OptionsMenu only in the Activity.
I get the OptionsItemsSelected on the Activity too.
When onOptionsItemSelected() occur, I get the current Fragment like this :
FragmentManager fg = getSupportFragmentManager();
Fragment frag = fg.findFragmentById(R.id.fragmentMap);
All my Fragment have the same id but I always get the Fragment on the top.
Then, I can call :
frag.onOptionsItemSelected(item);
to the Fragment receive and my UI is correctly update.
I hope It helps.

Try playing with setHasOptionsMenu(boolean) in your Fragment extending classes,
if that is set to true the FragmentManager should automatically call your current fragment's onOptionsItemSelected,
it set to false you can manually call those callbacks yourself in your Activity's onOptionsItemSelected.
Worked for me... :)

Related

Android. How to avoid fragment be recreated when back from another fragment?

I'm using MVP in my project. I have an activity. Inside this activity I'm showing fragment. Fragment contains some data, edit text, buttons etc. From this fragment it is possible to navigate to another fragment. Here is my code for showing another fragment:
getParentFragmentManager()
.beginTransaction()
.replace(R.id.main_container, secondFragment)
.addToBackStack(null)
.commitAllowingStateLoss();
Next, when I try to go back from fragment 2 to fragment 1, my fragment one is re-created.The method onViewCreated() is called again with saveedInstanceState = null. Also in the onViewCreated() I call presenter.onCreate(savedInstanceState) and because of this, all requests that should be called when I first enter the fragment are re-called when I back to first fragment.
As far as I understand, when calling a .replace(container, fragment), I cannot avoid recreating the fragment view, but in this case, how can I save all my data in the presenter so that I do not re-execute all requests when returning to the fragment?
P.S. With .add() fragment is not recreated. But in my activity I have toolbar with title, and I don't need it to show in my second fragment. When I open my second fragment with .replace() toolbar is not showing, but when open with .add() toolbar is showing.
Use Fragment Result API :
For implemention this method set - setFragmentResultListener - in source fragment and also set - setResult() and finish() - in destination fragment
Note 1 : for having clean code i suggest you to use FragmentTransaction class in:
https://github.com/mahditavakoli1312/FragmentTransaction---mahdi-tavakoli
Note 2 : use Navigation for navigate betwin fragments and activities Instead tranastion

Android: How to start a new fragment without destroying the state of the previous fragment?

How to replace Fragment_1 Fragment_2 with the ability to return back to the state and Fragment_1 (scroll, inputs, forms, other)?
enter image description here
If you use Activities, then you can use the method startActivityForResult. The work of this method perfectly shows the current task with fragments.
I do not want to save the values and then substitute them. We need that to Fragment_1 remained intact.
How to save the status of previous fragments at the opening of the new fragment_N and when you turn the screen using backstack?
Is there a ready library for the implementation of these tasks?
Instead of replacing fragment, You can add a new fragment and hide current one.
Something like this
FragmentTransaction t = getFragmentManager.beginTransaction();
t.hide(your_current_fragment);
t.add(container, new_fragment);
t.addToBackStack(TAG);
t.commit();
It will not loss the state of hidden fragment
FragmentTransaction t = getFragmentManager.beginTransaction();
t.hide(your_current_fragment);
t.add(container, new_fragment);
t.addToBackStack(TAG);
t.setCustomAnimations(R.anim.open_enter,R.anim.close_exit,R.anim.open_enter,R.anim.close_exit)
or
t.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
t.setTrans
t.commit();
replace FragmentPagerAdapter with a HorizontalScrollView contains 2FrameLayout for fragment.You can freely change fragment in FrameLayout.

What Fragments am I hosting and displaying?

Is there a way to know which Fragment is currently displayed in a given <fragment> container of an Activity without keeping track of all the changes via the onAttachFragment callback?
Is it even possible to know which fragments are displayed when fragment transactions can take place when the user presses the back key? In this latter case, i.e. when a Fragment is re-displayed due to a back, the onAttach is not called.
In my experience, the only way to know for sure which fragment is being displayed is to keep track of that carefully yourself.
For example, you could make a variable in your Activity:
Fragment mCurrentDisplayedFragment;
and then whenever the user requests a different fragment do:
mCurrentFragment = (Fragment) userRequestedFragment;
fragmentManager.replace(container, mCurrentFragment, tag);
Then, whenever you needed to do things to the currently displayed fragment, you could triage it by try/catching a cast or with instanceof.
You could also handle the back pressed behavior by overriding that method in the activity:
#Override
public void onBackPressed() {
int stackSize = fragmentManager.getBackStackEntryCount();
// This counts up from the bottom so the most recent fragment is the biggest number/size
backFragId = fragmentManager.getBackStackEntryAt(stackSize);
// Get a handle on the fragment that is about to be popped
mCurrentFragment = fragmentManager.findFragmentById(backFragId);
super.onBackPressed();
}
Also, are you sure that onAttach is not called when a fragment is popped off the stack? I seem to remember that it will be, and you can call through the interface created there (if you have one and the activity implements it) to register the fragment as the current fragment in the activity at the time.
But to directly answer your question, there isn't a built in way to just know what fragment is currently displayed (and there could be more than one!). The implementation details of that are up to you. Hopefully I've given you some ideas of how it could be handled though. You might also find the FragmentManager documentation helpful.
Each time when you add/replace fragment to the container, use tag for it:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.container, fragment, tag).commit();
then you can find out the fragment is current visible or not:
Fragment fg = getFragmentManger().findFragmentByTag(tag);
if(fg.isVisible())
//fg is the current visible fragment
Hope this help!

Android how to send data to a running fragment

is there a way to send some data from an activity to a running fragment?
In my app I'm adding a second fragment over another fragment. I intentionally use the add method instead of the replace method. So now I want to hide my second fragment with
fragmentManager.popBackStack();
and my first fragment reappears. After hiding the second fragment I want to send some data from my activity to the still running frist fragment.
Any idea how to do this? It doesn't work with bundles (put extra), because I don't rebuild the fragment, I just hide the second one!
one simple solution is:
MyFragment oldFragment = (MyFragment) fragmentManager.findFragmentById(R.id.fragment_place);
fragmentManager.popBackStackImmediate();
MyFragment newFragment = (MyFragment)fragmentManager.findFragmentById(R.id.fragment_place);
newFragment.postData(...);
You can use an EventBus library like this one, it's easy to use and very convenient.
You can use tags on the Fragments when you create them to call them when needed.
getFragmentManager().beginTransaction()
.add(R.id.content, new SomeFragment(), SomeFragment.class.getSimpleName())
.commit();
So above I use the simple name of the class to tag the fragment when I create and add it to the activity.
SomeFragment fragment = (SomeFragment) getFragmentManager().findFragmentByTag(SomeFragment.class.getSimpleName());
And I can call it back when I need it and know it is being displayed like above, now I can call send it data like normal by calling a public method in the custom fragment and passing it the data as a param.

FragmentManager popBackStack doesn't remove fragment

I'm implementing menu navigation using Fragments. So I begin with Home, and then users can navigate to diferent sections and details of each section.
When a user changes section, then I call pop on the fragmentmanager backstack until I reach Home, and then load the new section.
This is all working as expected. But I'm getting this problem:
load a section that calls setHasOptionsMenu(true) on onResume()
loads another section (old section it's suposed to get out of the stack). I see it OK. No menu is shown
leave the application (for example, go to Android Laucher activity) and then when I return, I see the correct section, but it's showing the Menu of the old Fragment.
I've iterated the backstack and printed each fragment, and there it's not the fragment with the menu.
I put a debug mark on the onResume() method (where the setHasOptionsMenu(true) is flagged) and it indeed enters here, so the Fragment it's still somewhere.
I want to know if I'm doing something wrong and how could I solve it, thx
Update:
I'm using this code to load new fragments
fm.beginTransaction()
.add(container, sectionFragment.getFragment())
.addToBackStack(sectionFragment.getFragmentName())
.commit();
And for remove:
private void clearStack(){
int count = fm.getBackStackEntryCount();
while(count > 1){
fm.popBackStack();
count--;
}
}
NOTE 1: I'm using add instead replace because I don't want to loose the state of my fragment when I navigate back from detail section. When I load another different section, then I call clearStack to pop the stack up to 1, and then loads new fragment. At the end, I'm calling executePendingTransactions() to finish to remove the fragments from the transaction.
NOTE 2: I'm seeing that it is entering on my fragment onDestroy() method, so it is suposed to be destroyed. But I don't know why it is getting called again when the Main activity resumes.
I found that the problem was not in the logic of adding and removing fragment of the stack.
The problem was that some of the fragment loaded another fragments inside of it (it had ViewPager component). Then I thought that when the fragment was removed then these fragments were removed too.
This is true ONLY if you use getChildFragmentManager() method. This method MUST be used when loading fragments inside other fragmets. If not, then the fragments are asociated with the fragments activity.
popBackStack will just revert your last FragmentTransaction.
If you use FragmentTransaction.add, popBackStack will just call FragmentTransacetion.remove.
But if you call FragmentTransaction.replace, popBackStack will call FragmentTransaction.remove and FragmentTransaction.add
For your "NOTE 1" :
FragmentTransaction.replace will not change your fragment state.
I found this question, because after calling
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
this code fragmentManager.getFragments().size() returns me the maximum number of fragments, which were in the stack. I checked every fragment on null. And I found that some fragment is null in my case. Maybe it will help someone)
If you are really looking to remove fragments at once then follow:
How to replace Fragments of different types?
Otherwise use replace transaction for fragments to smooth transitiona and hassel free approach, see https://stackoverflow.com/a/23013075/3176433
Also understand Fragment lifecycle,
http://developer.android.com/guide/components/fragments.html
I had a similar problem where the popBackStack() didn't remove my fragment.
However, I noticed that I called the wrong FragmentManager, where I had to call getSupportFragmentMananger() instead of getFragmentManager().
Maybe there is a <fragment> or <androidx.fragment.app.FragmentContainerView> in an activity with android:name="androidx.navigation.fragment.NavHostFragment", app:defaultNavHost="true" and app:navGraph="#navigation/nav_graph".
In this case navigation is held by nav_graph. If you don't want to use NavController and NavHostFragment, maybe you should remove navigation and clean <fragment> tag.

Categories

Resources