I have added 3 fragments to my Activity with
String name = "fragment1"; // and ..2 and ..3
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.content_frame, fragment, name);
fragmentTransaction.addToBackStack(name);
fragmentTransaction.commit();
The last added (third) Fragment now is visible on top.
Now I want to resume to the first added Fragment. But how?
I can find this Fragment with
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment firstFragment = fragmentManager.findFragmentByTag("fragment1");
If I call fragmentManager.getFragments() I still can find all three Fragments.
How to bring firstFragment back to top, make it visible again?
You can hide your 2nd and 3rd fragment and make your 1st fragment visible. So you'll have the effect that first fragment is shown on top and others are invisible.
solution:
Use the FragmentTransaction's show and hide method. Firs you need to find all the fragment and call the FragmentTransaction to show and hide 2nd and 3rd fragments.
Here's how I do it in my app when I want to switch to fragment:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
if (fragment.isAdded())
{
transaction.show(fragment);
}
else
{
transaction.replace(R.id.container, fragment);
}
transaction.addToBackStack(null);
transaction.commit();
Note the use of show.
It ended up with this:
/**
* #param tag name of the fragment to resume and to bring to top
* #return true if fragment has been found
*/
private boolean bringFragmentToTop(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment != null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
for (Fragment f : fragmentManager.getFragments()) {
if (f == fragment)
fragmentTransaction.show(f);
else
fragmentTransaction.hide(f);
}
fragmentTransaction.commit();
return true;
}
return false;
}
Related
I have two fragments one list and one detail fragment. On list item click I a hiding list fragment and adding detail fragment on back press detail fragment is popped automatically I am just calling super.onBackPressed() but issue is it is creating so many references of detail fragments resulting is memory leaks
Following is my code
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.hide(this);
ft.add(containerId, detailFragment, "detail");
ft.addToBackStack("detail");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
I don't want to view to be recreated view when user press back button on detail fragment thats why I used above approach. Also with current implementation when I press back button recylerview scroll possition and other data I don't have to save
My Activity has only following code it inflates list fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.FragmentContainer1, ListFragment.newInstance(), TAG).commit();
}
I think what you are doing wrong is that you are adding fragments each time to the container again and again by calling add method:
In your case you should use replace method and add your list fragment to the backstack. Here's how you should start your detail fragment:
FragmentManager fm = getFragmentManager();
fm.beginTransaction()
.replace(R.id.container, new DetailFragment())
.addToBackstack(null)
.commit();
To get back to your list fragment, which is in the back stack, just call:
fm.popBackStack();
EDIT:
Try this to show your list fragment:
protected void displayListFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (listFragment.isAdded()) {
ft.show(listFragment);
} else {
ft.add(R.id.flContainer, listFragment, "ListFragment");
}
if (detailFragment.isAdded()) {
ft.remove(detailFragment);
}
ft.commit();
}
And this to show your detail fragment:
protected void displayDetailFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (listFragment.isAdded()) {
ft.hide(listFragment);
}
if (!detailFragment.isAdded()) {
ft.add(R.id.flContainer, detailFragment, "DetailFragment");
}
ft.commit();
}
I have implemented fragments in my application. Here my code for swiching fragment in fragment_container.
private void switchFragment(Fragment fragment, boolean isAddToBackStack, String tag)
{
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, fragment, tag);
if (isAddToBackStack)
ft.addToBackStack(tag);
setCurrentTopFragment(Integer.parseInt(tag));
ft.commit();
}
I have 4 fragments A,B,C and D and for switching between this fragmnets I am using above method. I have A,C,B in my backstack. If again I switch to fragmnet A, my backstack is like A,C,B,A. What I actually want is If I swich to A again I want backstack sequence like this C,B,A. Means Remove old instance from backstack and add new to it.
First get the back-stacked Fragment by id which you need to remove:
Fragment fragment = getSupportFragmentManager().getFragment(new Bundle(), TAG_KEY)
or there are several methods getBackStackEntryCount(), getBackStackEntryAt. After getting the fragment which you need to remove. Remove it from the fragment back-stack.
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(fragment);
Then you can add a new fragment Done :)
I have one activity and 3 fragments A,B,C when app starts it holds main Fragment A then from Fragment A i'm navigating to Fragment B and from Fragment B to Fragment C. Code works and it opens Fragment C from Fragment B, but first it opens Fragment A and just then Fragment C. Why and how can I fix this? Do I need one more activity to host Fragments B,C?
Method which switches fragments:
private Fragment contentFragment;
public void switchContent(Fragment fragment, String tag){
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
while (fragmentManager.popBackStackImmediate());
if (fragment != null){
FragmentTransaction transaction = fragmentManager
.beginTransaction();
transaction.replace(R.id.content_frame,fragment,tag);
if (!(fragment instanceof FragmentB)){
transaction.addToBackStack(tag);
}
transaction.addToBackStack(tag);
transaction.commit();
contentFragment = fragment;
}
}
R.id.content_frame is id of Layout which is used on activity setContentView.
This happens because you're popping all fragments in back stack before replace current fragment with the next one.
You don't need this line:
while (fragmentManager.popBackStackImmediate());
Also, this part is pointless:
if (!(fragment instanceof FragmentB)){
transaction.addToBackStack(tag);
}
transaction.addToBackStack(tag);
because the last line ignores condition.
If you wish to add fragments to back stack except FragmentB, then try to edit your code next way:
public void switchContent(Fragment fragment, String tag) {
if (fragment != null) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.content_frame, fragment, tag);
if (!(fragment instanceof FragmentB)){
transaction.addToBackStack(tag);
}
transaction.commit();
contentFragment = fragment;
}
}
I am navigating from one fragment to another fragment but my title alone changes my screen remains same. In the background the new fragment is up and running. This happens only when i navigate during any api call in the background.
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (main_fragment_container != null) {
ft.replace(main_fragment_container.getId(), fragment, fragment.getClass().getName());
}
if (isStackNeeded) {
ft.addToBackStack(fragment.getClass().getName());
}
ft.commit();
I have a button in my fragment (fragment_x) with the below OnClickListener:
private void onClickAddButton(View view){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment_y fragment_y = new Fragment_y();
fragmentTransaction.add(R.id.rl_activity_main_container, fragment_x);
fragmentTransaction.commit();
}
The problem is that this button is always visible, so clicking it again will add one more fragment_y and the screen gets messed up. How how do I check whether fragment_y has already been added, so that I can avoid creating a duplicate fragment_y?
You can ask the FragmentManager if the Fragment is already added:
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentByTag(tag);
if (fragment == null) {
// fragment must be added
fragment = new Fragment();
fm.beginTransaction().add(R.id.container, fragment, tag);
} else {
// fragment already added
});