I have two questions:
I want to remove all fragments in back-stack when user come back to main page.
However when I call following statement there is a flickering on the main page.
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
how to remove this flickering? I tried the method here no luck.
Pop the fragment backstack without playing the Pop-Animation*
In fragment transition i use replace method. But in some
transitions I dont want to reload the entire data when user presses
the back button. To implement this I used hide() and add() methods.
When this is done above back-stack remove process becomes really bad
with so many animations.
Is there a best practice to implement this?
I had exactly the same issue as (1). Here is what worked for me:
the transaction that shows the first fragment is added to the backstack using a named backstate, eg: "bottom".
the backstack is cleared with popBackStackImmediate("bottom", ...INCLUSIVE).
So, whenever I want to replace whatever is in the backstack with a new fragment I use the following function:
protected void showInitialFragment(Fragment fragment) {
getSupportFragmentManager()
.popBackStackImmediate(BOTTOM_BACK_STATE, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_content, fragment)
.addToBackStack(BOTTOM_BACK_STATE)
.commit();
}
I also had to override onBackPressed() like this:
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
finish();
} else {
super.onBackPressed();
}
}
Hope this helps!
Found an easy method https://stackoverflow.com/a/67005552/7418129. Sorry if I'm late. But it will definitely help someone.
The best solution for me was to add setReorderingAllowed(true).
Example:
parentFragmentManager.commit {
setReorderingAllowed(true)
addToBackStack(null)
setCustomAnimations(R.anim.enter_right, R.anim.exit_left, R.anim.enter_left, R.anim.exit_right)
replace<AnotherFragment>(R.id.fragment_container)
}
Related
I have a fragment, called SplashScreenFragment. He is adding in onCreate of application with call of
supportFragmentManager.beginTransaction()
.replace(R.id.host_root, SplashScreen())
.commit()
After 3 seconds I replacing this fragment with another one, calling
activity?.supportFragmentManager?.beginTransaction()
.replace(R.id.host_root, fragment, fragment.tag())
.addToBackStack(null)
.commit()
But when I'm pressing back button, Im returning to my SplashScreen, but I wanna exit an application. How to fix this?
Remove ".addToBackStack(null)"
This code means your fragment to add backstack.
addToBackStack(String)
#Override
public void onBackPressed() {
}
If this is not critical for you, you can override the onBackPressed call and do nothing
I have fragment A and adding fragment B in same container (not replacing). I am adding this transaction on backstack also. Now, when device back is pressed, fragment B will be removed and fragment A will become visible. I want to do something when fragment A becomes visible. I searched lot but could not find anything helpful.
Note - I don't want to add backstackchangelistner and call onResume on that fragment.
You can override onHiddenChanged(boolean hidden) in a Fragment.
This will be called when its shown/hidden.
I use the same approach in my app, where i add a fragment and hide the old one, and then use the onHiddenChanged callback when the user presses Back, and the old fragment is shown again.
As you have 2 entries in Back stack, you can check back stack count on
Back Pressed method.
FragmentManager mFragmentManager = getSupportFragmentManager();
int count= mFragmentManager.getBackStackEntryCount();
if(count==1){
// do your work
}
you can try
#Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
}
or
`fragment.isVisible();`
I've got a navigation drawer. In that navigation drawer I've got five fragments. When I select a fragment, it shows up. When I press the back button, it goes to the previous fragment. However, I need the back button to send you back to the first fragment. How do I do this?
Overwrite the onBackPressed() method in your Activity:
#Override
public void onBackPressed(){
FragmentTransactionn ft = getFragmentManager().beginTransaction();
ft.replace([your fragment container], yourfirstFragment, TAG_FRAGMENTFIRST);
ft.commit();
}
Apparently you already figured out how to show fragments. I'd suggest using the same code you use in your navigation drawer in the public void onBackPressed() to draw up the first fragment again. To make users able to exit the app, check if the first fragment is already visible. If so, call super.onBackPressed() or finish().
I have a problem that I've been dealing with for the last couple o days and don't seem to find an answer to it.
Description : I have a main activity which contains a navigation drawer. Each item of the navigation drawer (when clicked) creates a fragment. In that fragment, there is a listView of objects, which creates other fragments when clicked. In those fragments i have another listView of objects which opens other fragments. In other words, there series of fragment that open other fragment. Something like this:
http://s22.postimg.org/pddo5gsv5/backstack.png
In order to be able to get back to each fragment, I've implemented the addToBackstack("string") method.
My question is, how can I implement correct backstack for my application so that when i click a navigation Drawer item, all the fragments that have been added to backstack are cleared, without the one that the navigation Drawer item opens.
Any help would be appreciated. Thank you !
EDIT
Ok, it seems I managed to figure it out. Considering what advices i received from the replies, here's the solution I came up with:
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count != 0) {
FragmentManager.BackStackEntry backEntry = getFragmentManager()
.getBackStackEntryAt(
getFragmentManager().getBackStackEntryCount() - 1);
if (backEntry.getName() == NAVIGATION) {
finish();
} else
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
To put it in words: First, i added a backstack entry even for the top level fragments, given them a specific tag. The I have overridden the Activity's back button function so that when the last backstack entry is a top-level fragment to finish the activity (so that it not simply detach the fragment from activity, living it empty). Otherwise, if the last entry isn't an top-level fragment, execute a popBackStack.
PS: All non-top-level fragments are added to the backstack with a different tag then the top-level one. Also, i had to do a POP_BACK_STACK_INCLUSIVE in the navigation Drawer's click listener.
getFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
Thank you all for the advices and hopefully this EDIT help other users.
You can use the following code to solve your problem:
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(fragment_tag)
.commit();
In order to make the code above work, you have to create the fragments dynamically. As hardcoded fragments cannot be replaced. To do that, you can create a container (FrameLayout etc.) which in our example has the id fragment_container. Then, the code above will add the fragment in the container dynamically. Finally, you have to pass as parameter in the addToBackStack method the fragment_tag. That means, that this transaction will be added in the back stack. And finally, in order to get it from the backstack you have to use the code below:
getFragmentManager().popBackStack(fragment_tag, FragmentManager.POP_BACK_STACK_INCLUSIVE));
The POP_BACK_STACK_INCLUSIVE flag, insures that "all matching entries will be consumed until one that doesn't match is found or the bottom of the stack is reached. Otherwise, all entries up to but not including that entry will be removed."
You can clear the fragment backstack by using something like:
fragmentManager.popBackStack("string", FragmentManager.POP_BACK_STACK_INCLUSIVE);
and then you can addToBackstack and commit as usual. More info.
A code snippet that shows the way I normally use it in navigation drawers:
FragmentManager fragmentManager = getSupportFragmentManager();
if(clearBackStack) {
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
if(!clearBackStack) {
ft.addToBackStack(null);
}
ft.commit();
The main activity opens the main_fragment with this transaction:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.fragment_main_container, new MainFragment())
.commit();
}
Then I replace that fragment with another one like this:
// method to handle Conversions button click
public void addConversionsFragment (View v) {
// replace the main fragment with the conversion fragment
UnitConversionFragment newFragment = new UnitConversionFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
transaction.replace(R.id.fragment_main_container, newFragment);
// and add the transaction to the back stack so the user can navigate back
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
Originally, I was using support.v4.app.fragment, and everything was working as expected (back button in the second fragment would pop that one out and return to the MainFragment. But then I decided to implement a PreferenceFragment elsewhere, which the support library didn't seem to like. So I converted the whole project to the regular app.fragment by deleting all the support imports, replacing with the regular imports, then editing all the getSupportFragmentManager() with getFragmentManager(), etc.
Good news is thePreferenceFragment works well, however any time I hit the back button in a fragment, it closes the hosting activity rather than reversing the transaction.
I did many searches and it seems that I am implementing the code correctly, but it is just not responding as I am expecting. Is there more involved in converting away from the support library? Or am I missing something else obvious? I saw a lot of answers out there overriding the onBackPressed(), but I really don't want to do that.
Is there some fundamental difference between the v4 support library and the regular library that requires me to handle the fragment transactions differently?
Preference Fragment has a bit of extra logic to handle hierarchical preferences. You can configure it to launch sub fragment screens, and navigate back, as demonstrated here.
<PreferenceScreen android:title="Sub Preferences"
android:fragment="com.example.SettingsDemo.SubPrefFragment"/>
For normal fragments , fragment back-stack pops first before reaching Activity back stack. This is what is documented.
The code in both android.app.Activity and android.support.v4.app.FragmentActivity is exactly same:
/**
* Take care of popping the fragment back stack or finishing the activity
* as appropriate.
*/
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
The only reason it is not happening as expected is that something else consumes "back press", this may happen when there are 3 levels of components:
The Activity is inside an ActivityGroup.
Fragment is inside another Fragment. (for this, there are some bugs with v4 fragments).