I'm using one Activity which contains one Fragment at a time. I use support.v4.
The "onBackPressed" of Activity and Fragment is override, so I can't use the original back button, I have to override it myself.
So I'm in fragment A, I go to fragment B. Fragment B displays a list of results, and when I pick a line, it goes to Fragment C.
When I'm on C and I press back button, I want to go back on B with the results displayed. And if I press back button again, I'll go to A.
It looks simple.
I manage the come back from C to B. The thing is when I hit the back button on B, it calls Fragment C backPressed.
A -> B -> C -> B (display B but BackButton don't work anymore).
Some code :
backPressed in Fragment C
public void backPressed() {
FragmentTransaction transaction = ((FragmentActivity)m_context).getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.mainactivity_fragmentcontainer,((FragmentActivity)m_context).getSupportFragmentManager().findFragmentByTag("customtag"), "customtag");
transaction.commitAllowingStateLoss();
}
Fragment B has the tag "customtag".
When I replace B by C:
FragmentC newFrag = new FragmentC(m_context);FragmentTransaction transac = ((FragmentActivity)m_context).getSupportFragmentManager().beginTransaction();
((FragmentContainerActivity)m_context).setCurrentFragment(newFrag);
transac.replace(R.id.mainactivity_fragmentcontainer, newFrag);
transac.addToBackStack(null);
transac.commitAllowingStateLoss();
Any idea why the fragmentC which is replaced (the display changes and I can see fragment B) still get the back button action?
Thanks for your help.
EDIT
Code of backPressed in Fragment B (however the application never goes there when it comes from Fragment C).
#Override
public void backPressed() {
Log.e("FragmentB", "backPressed");
//I have 2 views in FragB. If View2 is visible, I make it gone and display View1
if(mainView.findViewById(R.id.view2).getVisibility()==View.VISIBLE){
displayView1();
}else{
if(fromFragmentX){
FragmentX fragX = new FragmentX(ctx);
FragmentTransaction transac = ((FragmentActivity)ctx).getSupportFragmentManager().beginTransaction();
((FragmentContainerActivity)ctx).setCurrentFragment(fragX);
transac.replace(R.id.mainactivity_fragmentcontainer, fragX);
transac.commitAllowingStateLoss();
}else{
super.backPressed();
}
}
}
SECOND EDIT
I realize I forgot to precise something.
When I'm replacing fragment B by fragment C, I'm doing it in the ArrayAdapter of the ListView in Fragment B, but it shouldn't change anything.
Anyway, I tried something different somewhere else in the app.
In FragmentU, I replace FragmentU by Fragment C (always the same), and I'm setting an attribute in Fragment C which is :
private CustomFragment fragmentFrom;
So on backPressed in FragmentC, in case I'm from Fragment U, I call :
FragmentTransaction transaction = ((FragmentActivity)ctx).getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.mainactivity_fragmentcontainer, fragmentFrom);
transaction.commitAllowingStateLoss();
And I still got the same problem. When coming back from Fragment C, the Fragment U is displayed, and works well, but the back button call FragmentC.backPressed.
Related
I have 3 fragments A, B and C with A being the start destination of my nav graph. When the user starts the app, I check in fragment A if there are previously stored results. If there are, I want to navigate straight to fragment C. I have managed to get this to work. However, when the user presses back in fragment C in this case, I want them to be taken to fragment B instead of A, and that's what I need help figuring out.
Note: Fragment A is just a setup fragment which is only visited once when the app starts. Which means when the user presses back from fragment B, they are taken to OS home screen.
You can override onBackPress() and replace whatever fragment you are in with FragmentB like this
#Override
public void onBackPressed() {
int stackCount = getFragmentManager().getBackStackEntryCount();
if (stackCount == 1) {
super.onBackPressed(); // if you don't have any fragments in your backstack yet.
} else {
// just replace container with fragment as you normally do;
FragmentManager fm = getFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);//clear backstackfirst and then you can exit the app onbackpressed from home fr
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.container, new FragmentB());
transaction.commit();
}
}
This is the original answer ,you can take a look answer by Rainmaker
You can override your onBackPressed on fragment C and call your navController to go back to fragment b creating a new action from C to B
navController.navigate(R.id.action_CFragment_to_BFragment)
I currently have an android app that flows A -> B -> C -> D Launched in activity 1.
After D, I have activity 2 start and the following code runs to remove all fragments from the stack.
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
}
My problem is that when I return to activity 1 from activity 2, is that when I press the back key Fragment C animates back to screen. Fragment D does remove but A B C do not. I would like the app to close on backpress from activity 1.
I attached the code that removes my fragments here. Debugging shows that fragment does change with each loop.
Can anyone advise what is happening here?
You can overwrite backpressed method and close the app, like this:
#Override
public void onBackPressed() {
finish(); // finish activity
}
I have 5 fragments(say A, B, C, D, E) and one activity with a container.
Whenever i want to add a fragment to a container I'll be using the following code.
getSupportFragmentManager().beginTransaction().replace(R.id.mainContainerRL, fragment, tag).addToBackStack(tag).commit();
Let's say i added Fragment A.
Upon some action in A, I added fragment B.
Upon some action in B, I added fragment C.
Upon some action in C, I added fragment D.
Upon some action in D, I added fragment E.
Now my stack should be as follows.
A -> B -> C -> D -> E
Now upon some action in Fragment E, I need to remove fragments D, C, B so that when user click back, he should directly see Fragment A.
I tried using following code.
public void removeScreen(#NonNull String tag) {
FragmentManager manager = getSupportFragmentManager();
Fragment fragment = manager.findFragmentByTag(tag);
if (fragment != null) {
FragmentTransaction trans = manager.beginTransaction();
trans.remove(fragment);
trans.commitAllowingStateLoss();
}
}
Upon some action in Fragment E, I called the above function with Tags of Fragment D, C, B(Tags are same as the one that i used for fragment transaction).
Now when i click back button fragment D is becoming visible but i was expecting fragment A.
It would be very helpful if somebody points out where am i going wrong.
If you want to reach exactly the same behavior that you've described, you can do it by this way:
FragmentManager manager = getSupportFragmentManager();
manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
This will clear all backstack until the bottom of stack will be reached.
I prefer using DialogFragment for this reason and pop them using interface callbacks and dismiss() function inside them. This is the easiest and quick way to implement what you are trying to do.
I think your problem occur here :
replace :
getSupportFragmentManager().beginTransaction().replace(R.id.mainContainerRL, fragment, tag).addToBackStack(tag).commit();
to:
getSupportFragmentManager().beginTransaction().add(R.id.mainContainerRL, fragment, tag).addToBackStack(tag).commit();
when you add your fragment to container,tou just add it ,if use"replace" method,you romove it from activirty's fagment manager,it case your "removeScreen" method did not work
I have one Activity that hosts many Fragments. In Fragment A, I am adding a dialog when the user presses the back button to ask if they are sure if they want to leave this fragment. I added this code in the Activity's onBackPressed to control this:
#Override
public void onBackPressed() {
FragmentA fragmentA = (FragmentA) getSupportFragmentManager().findFragmentByTag("fragmentA");
if (fragmentA != null && fragmentA.isVisible()) {
fragmentA.showExitDialog();
return;
}
else { super.onBackPressed(); }
}
And the dialog works perfectly in Fragment A, but when it leaves Fragment A and goes to Fragment B (same activity) with this code:
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.container,
FragmentB.newInstance(), "fragmentB").commit();
And I press the back button in Fragment B, it shows the same exit dialog again.
Thus, from my code, it is saying that FragmentA is not null and still visible even after I did the Replace function.
Why is Fragment A still visible when I replaced it with Fragment B?
I have this issue in Android. Consider three Fragments: A, B, C. C can be called from A or from B. Is there anyway to know from which fragment, C was called?
Edited
Ok guys I'm going to explain what I'm trying to do. Suppose I have this call: A calls B, B calls C.
When I press the back button in C It gets me to B, thats fine. But when I press the back button again, it takes me to C, instead of A.
This is my code:
#Override
public void onBackPressed() {
//this is the current fragment
Fragment fragmentActual = this.getSupportFragmentManager().findFragmentById(android.R.id.tabcontent);
String fragmentTag = fragmentoActual.getTag().toString();
//If I press the back button in C:
if(fragmentTag.equals("TAG C")){
Fragment removefragment = this.getSupportFragmentManager().findFragmentByTag("TAG B");
Fragment fragmentClient = this.getSupportFragmentManager().findFragmentByTag("TAG C");
//If Im NOT passing arguments to B, I know this is a new form
if(removefragment.getArguments()== null){
//I always pass arguments to fragment C, but just in case:
if(fragmentClient.getArguments()!= null){
Bundle mArguments = fragmentClient.getArguments();
//FRAGMENT B
FragmentB fragmentB = new FragmentB ();
fragment.setArguments(mArguments);
FragmentManager manager = this.getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.addToBackStack(null);
ft.replace(android.R.id.tabcontent,fragmentB,"TAG B");
ft.commit();
}
}else{
super.onBackPressed();
}
}else{
super.onBackPressed();
}
}
Now I'm going to explain the code. Basically what it does is to replace fragment B, when fragment C is called. I do this, because I need to pass arguments to fragment B. But when I do the replacement, the "history" of the fragment B is lost, I mean when I press back button in B, I cant go back to fragment A (HERE IS WHY I WANTED TO KNOW IF I CAN KNOW WHO CALLS WHOM).
The firts time when I call fragment B, I dont pass arguments because is a blank form. But when I call to C, staying in B, I need to pass arguments to fragment B (when back button is pressed), so It can shows updated information.
Please if there something that is not clear, let me know so I can explain myself better.
Edited 2: This issue has something with this https://stackoverflow.com/questions/16703604/back-press-button-when-i-save-a-form-for-the-first-time-a-list-view-is-not-updat. Maybe it does my idea more clear.
The answer of Luksprog I think is the best: "You may want to tackle those issues. You always have the option of passing a Bundle with data to the newly created fragment mentioning who called it. Then using getArgument() in the fragment will know who called it.".
I haven't found another better way.
You can use the setTargetFragment method to set which was the parent fragment. Then you can use the method getTargetFragment to find out who called you.
What you are doing is transitioning between Fragments, call addToBackStack() as part of your FragmentTransaction:
i guess, This is what you need.
private final static String TAG_FRAGMENT = "TAG_FRAGMENT";
private void showFragment() {
final Myfragment fragment = new MyFragment();
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not
super.onBackPressed();
}
}
You can use FragmentManager for creating a back stack of your fragments. You also have to work with Fragment Transactions first. Further informations see: http://developer.android.com/guide/components/fragments.html#Transactions