web-dev-qa-db-fra.com

Comment remplacer le fragment C par le fragment A lorsque le bouton de retour est enfoncé?

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?

34
Harshal Kshatriya

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; -).

17
hcpl

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