Mon scénario: l'activité 1 se compose des fragments A-> B-> C. Tous les fragments sont ajoutés à l'aide de ce code:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, fragment, TAG);
ft.addToBackStack(TAG);
ft.commit();
Maintenant, à partir du fragment C, je veux revenir directement au fragment A. Par conséquent, j'ai commenté ft.addToBackStack(TAG)
tout en ajoutant le fragment C. Donc, lorsque j'appuie sur le bouton de retour de C, j'obtiens directement le fragment A à l'écran.
Cependant, le fragment C n'est pas remplacé par A. En fait, les deux fragments sont visibles. Comment résoudre ce problème?
Théorie
Utilisez la méthode addToBackStack(tag:String):FragmentTransaction
à partir de FragmentTransaction
afin de marquer un point où vous souhaitez revenir. Cette méthode renvoie l'instance FragmentTransaction
pour la capacité de chaîne uniquement.
Revenez ensuite avec la méthode popBackStackImmediate(tag:String,flag:int):void
de FragmentManager
. La balise est ce que vous avez spécifié auparavant. Le drapeau est soit la constante POP_BACK_STACK_INCLUSIVE
pour inclure la transaction marquée ou 0
.
Exemple
Ce qui suit est un exemple avec la disposition suivante ayant un FrameLayout
avec id content_frame
où les fragments sont chargés.
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:paddingBottom="@dimen/activity_vertical_margin"
Android:paddingLeft="@dimen/activity_horizontal_margin"
Android:paddingRight="@dimen/activity_horizontal_margin"
Android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
Android:id="@+id/textView"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@string/hello_world" />
<FrameLayout
Android:id="@+id/content_frame"
Android:layout_below="@id/textView"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</RelativeLayout>
Le code ci-dessous marque un fragment par son nom de classe de fragment lors du remplacement du contenu de l'élément layout par id content_frame
.
public void loadFragment(final Fragment fragment) {
// create a transaction for transition here
final FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
// put the fragment in place
transaction.replace(R.id.content_frame, fragment);
// this is the part that will cause a fragment to be added to backstack,
// this way we can return to it at any time using this tag
transaction.addToBackStack(fragment.getClass().getName());
transaction.commit();
}
Et pour compléter cet exemple, une méthode qui vous permet de revenir à ce même fragment exact en utilisant la balise lorsque vous l'avez chargée.
public void backToFragment(final Fragment fragment) {
// go back to something that was added to the backstack
getSupportFragmentManager().popBackStackImmediate(
fragment.getClass().getName(), 0);
// use 0 or the below constant as flag parameter
// FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
Lors de l'implémentation de ceci pour de vrai, vous voudrez peut-être ajouter une vérification nulle sur le paramètre de fragment; -).
Vous devez faire 2 choses - nommez la FragmentTransaction de A-> B puis remplacez onBackPressed () dans votre activité de conteneur pour appeler FragmentManager # popBackStack (String name, int flags) lorsque vous êtes sur le Fragment C . Exemple:
Transition de A-> B
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, new FragmentB(), "FragmentB")
.addToBackStack("A_B_TAG")
.commit();
La transition de B-> C utilisera une transaction similaire avec "FragmentC" comme balise.
Ensuite, dans votre activité contournant onBackPressed ():
@Override
public void onBackPressed() {
if (getSupportFragmentManager().findFragmentByTag("FragmentC") != null) {
// I'm viewing Fragment C
getSupportFragmentManager().popBackStack("A_B_TAG",
FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
super.onBackPressed();
}
}