Fragments attached to a parent activity and back button - android

I would like to ask something about BackStackFragments. Let us suppose we have 2 buttons in an app. When each on them is clicked the a new fragment starts and shown in the screen.
if (buttonIndex == 0) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(android.R.id.content,new FirstFragment());
ft.addToBackStack("added first");
ft.commit();
} else if (buttonIndex == 1) {
FragmentTransaction ft1 = fragmentManager.beginTransaction();
ft1.replace(android.R.id.content,new SecondFragment());
ft1.setTransition(ft1.TRANSIT_FRAGMENT_OPEN);
ft1.addToBackStack("added second");
ft1.commit();
}
Now you see what is happening.But here is my question.
I click the first and the second button and both fragments are added in the
stack. No problem:). But if I click let's say the second button 3 times,
then the corresponding fragment will run 3 times as well. Meaning that
I have to click the back button 3 times so as to go back in the first fragment.
Is this supposed to be happening?
Regards,
Theo.

You can add a tag while add/replace a fragment. Then u should check if the same fragment is added once. if yes then remove the existing one.
FragmentTransaction ft = fragmentManager.beginTransaction();
Fragment prev = getFragmentManager().findFragmentByTag("FirstFragment");
if (prev != null) {
ft.remove(prev);
}
ft.replace(android.R.id.content,new FirstFragment(),"FirstFragment");
ft.addToBackStack("added first");
ft.commit();
A good example is shown here in DialogFragment implementation

Related

findFragmentById on back button becomes blank as size becomes zero

Here's my Flow/Structure:
Activity
Fragment
Same Fragment within it.
I have overriden removeCurrentFragment() method which does go back functionality by removing Fragment by ID as follows -
#Override
public void removeCurrentFragment() {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.fragment);
if (currentFrag != null)
transaction.remove(currentFrag);
transaction.commit();
}
It seems, when this happens, as ID of both fragment is same, it creates blank view.
If more details are required, please feel free to ask in comments. I will edit question as per required details.
I thought it was related to remove fragment, But I made new fragment with separate XML, still I am having the same issue.
I have parent fragment with pagination (as I need horizontal page scroll) in it have the child fragment, when clicking on child fragment button new fragment is replaced so when it is removed the X and Y of the child fragment is also disturbed.
here is the before and after screenshot of the x and y axis of child fragment.
Before
After
can any one suggest what could be the issue?
You have to use a tag to load the Fragment, and then use that same tag again to remove it.
For example, to add the Fragment:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
fragmentManager.popBackStack(tag, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.setCustomAnimations(R.anim.enter, R.anim.exit);
ft.add(containerId, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
To remove it, again use the same tag:
if (fragmentManager.findFragmentByTag(currentTag) != null) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.remove(fragmentManager.findFragmentByTag(currentTag));
ft.commit();
}

Memory leak on fragment transaction

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();
}

Android: Check if fragment exits in Stack and reuse it

Hi I am using a Stack variable for storing the sequence of fragments clicked by the user
For example : [A,B,C,A,D]
Now I need to check if a fragment exits in the stack I need to reuse it.
From the above example I need to reuse the first element i.e, A when user clicks on the fourth time.
The problem is I have a custom keyboard opening in fragment A, now if the same fragment is in the stack as forth element the keyboard is not opening .but when I backpress and go to first element keyboard is opened in the first instance of A
Code for storing in the Stack
public void switchContent(Fragment fragment) {
if(mContent !=null && (fragment.getClass().toString().equals(mContent.getClass().toString()))){
getSlidingMenu().showContent();
return;
}
mContent = fragment;
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.add(R.id.content_frame, mContent);
FragmentChangeActivity.fragmentStack.lastElement().onPause();
FragmentChangeActivity.fragmentStack.push(mContent);
ft.commit();
getSlidingMenu().showContent();
}
Code for backpress
#Override
public void onBackPressed() {
if (fragmentStack.size() >= 2) {
FragmentTransaction ft = fragmentManager.beginTransaction();
fragmentStack.lastElement().onPause();
ft.remove(fragmentStack.pop());
fragmentStack.lastElement().onResume();
ft.show(fragmentStack.lastElement());
ft.commit();
} else {
super.onBackPressed();
}
}
Any help is appreciated.
The following code check's if Fragment named SearchFragment exists or not in backstack and processes accordingly. You can use this logic to determine if a specific Fragment exists or not
FragmentManager fragmentManager=getSupportFragmentManager();
Fragment currentFragment = (Fragment)fragmentManager.findFragmentById(R.id.mainContent);
if(currentFragment!=null && currentFragment instanceof SearchFragment){
//SearchFragment exists in backstack , process accordingly
}else{
//SearchFragment not present in backstack
}

getFragmentManager().popbackstack() causing nullpointer exception

I am developing an android app with lots of fragments in it. But I am facing problems in switching between them.
Lets say I have a Fragment A now I want to go to Fragment B, for this I am doing like this--
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager
.beginTransaction();
Fragment fragment = new Fragment_B();
transaction.add(R.id.frameLayout, fragment);
transaction.addToBackStack(null);
transaction.commit();
I reach Fragment B successfully. Now I have to go to Fragment C from here, for this again I am doing the same thing.
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager
.beginTransaction();
Fragment fragment = new Fragment_C();
transaction.add(R.id.frameLayot, fragment);
transaction.addToBackStack(null);
transaction.commit();
I do this successfully also. Now I have to revert back to Fragment B, for this I do -
getFragmentManager.popbackstack();
This brings me back to Fragment B. But when I do the same to go to Fragment A now, it causes NullpointerException.
What I am doing wrong here. Why does this run perfectly for the first time but fails at the second time? Please help.
I think you have to check first there are fragment available in backstack or not. follow my below code:
if(manager.getBackStackEntryCount()>0){
manager.popBackStack();
manager.beginTransaction().commit();
}
Thats it...
and yes you do not add fragment a to backstack initally so crosscheck that..
fragmentTransaction.addToBackStack("tag");
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 1) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}

How to prevent displaying multiple fragments over each other

I have a multiple-dialog-fragment layout. In the large layout, I show them as dialogs and there's no problem:
fragment.show(fragmentManager, "fragment_dialog");
But in normal devices, I am using a fragment transaction and replace fragments as below:
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.replace(R.id.fragment_container, fragment).addToBackStack(null).commit();
The problem is that in normal devices, when I press the menu button twice (or more), the same fragment will be shown over the previous one. Is there a way to find out which fragment is visible right now and prevent it from opening again?
First of all, add tag to when you replace
transaction.replace(R.id.fragment_container, fragment, "fragment_foo")
.commit(); // etc
then make a control
if (fragmentManager.findFragmentByTag("fragment_foo") == null){
// do something
}
You can find fragment by tag:
if (fragmentManager.findFragmentByTag("fragment_dialog") == null) {
//show dialog here
}
// Replace fragmentCotainer with your container id
Fragment currentFragment = fragmentManager.findFragmentById(R.id.fragmentCotainer);
// Return if the class are the same
if(currentFragment.getClass().equals(fragment.getClass())) return;

Categories

Resources