Retour par programme au fragment précédent du backstack


218

Disons que j'ai une activité qui a des fragments ajoutés par programme:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

Quelle est la meilleure façon de revenir au fragment précédent qui était visible?

J'ai trouvé la fonctionnalité de déclenchement du bouton de retour sur le clic de bouton dans Android, mais je pense que simuler un événement de touche arrière n'est pas la bonne façon de procéder (et je ne peux pas non plus le faire fonctionner):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

L'appel finish()ferme simplement l'activité qui ne m'intéresse pas.

Y a-t-il une meilleure façon de procéder?

Réponses:


354

Regardez les getFragmentManager().popBackStack()méthodes (il y en a plusieurs parmi lesquelles choisir)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack ()


91
getFragmentManager().popBackStackImmediate();a fait l'affaire. Merci.
Aske B.

1
Où pourrais-je mettre cette méthode? Dans mon écouteur d'onglets?
rasen58

1
sans voir le code, c'est difficile à dire ... mais il faut aller dans la section de code qui est exécutée quand on veut "fermer" le fragment courant et revenir au fragment précédent.
Stuckless

1
Qu'en est-il de getSupportFragmentManager ()
ViliusK

5
N'oubliez pas d'ajouter "addToBackStack (" tag ")" dans votre code. "fragmentManager.beginTransaction (). replace (R.id.content_frame, fragment) .addToBackStack (" tag "). commit ();" si vous écrivez addToBackStack (null), il le gèrera lui-même mais si vous donnez une balise, vous devez la gérer manuellement.
Khaled Saif

129

Pour développer les autres réponses fournies, voici ma solution (placée dans une Activité):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}

5
et pourquoi cela se produit-il. Dans l'exemple de fragment developer.android.com/training/basics/fragments/index.html, ils ne remplacent pas un événement contre-pressé et pourtant ils sont capables de backstacker un fragment. J'ai utilisé trasaction.addToBackStack (null); mais rien ne se passe. Pouvez-vous expliquer pourquoi ?
Murtaza Khursheed Hussain

@MurtazaHussain, vous devriez probablement poser une nouvelle question si vous voulez de l'aide à ce sujet. Il est un peu difficile de voir ce qui se passe sans regarder plus de code.
Kyle Falconer

2
Dans mon cas, j'ai dû le faire fm.getBackStackEntryCount() > 1pour rappeler l'activité alors qu'il n'y a que le premier fragment dans la pile.
Facundo Olano

3
Android le fait déjà pour vous: "Lorsqu'il y a des objets FragmentTransaction sur la pile arrière et que l'utilisateur appuie sur le bouton Retour, le FragmentManager fait disparaître la transaction la plus récente de la pile arrière et effectue l'action inverse (telle que la suppression d'un fragment si la transaction l'a ajouté). " (Source)
artkoenig

29

Lorsque nous mettons à jour / ajoutons les fragments,

Devrait inclure le .addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

Après cela, si nous donnons le getFragments.popBackStackImmediate()retourne vrai si nous ajoutons / mettons à jour les fragments et revenons à l'écran actuel.


7

Ajoutez ces lignes à votre méthode onBackPressed (). La méthode popBackStackImmediate () vous ramènera au fragment précédent si vous avez un fragment sur la pile arrière `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

"


5

Cette solution fonctionne parfaitement pour la navigation de fragments basée sur la barre inférieure lorsque vous souhaitez fermer l'application lorsque vous appuyez à nouveau sur le fragment principal.

D'un autre côté, lorsque vous ouvrez le fragment secondaire (fragment en fragment) qui est défini comme "DetailPizza" dans mon code, il retournera l'état précédent du fragment primaire. À votre santé !

Les activités intérieures sur le dos pressé mettent ceci:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

Et lancez l'autre fragment comme ceci:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();

3

Ces réponses ne fonctionnent pas si je n'ai pas addToBackStack () ajouté à ma transaction de fragment mais, vous pouvez utiliser:

getActivity().onBackPressed();

de votre tout fragment pour revenir en arrière;


1

Revenez par programme au fragment précédent en utilisant le code suivant.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();

1

Pour faire revenir ce fragment, ajoutez simplement ce fragment au backstack sur lequel vous souhaitez revenir appuyé, par exemple:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

Dans le cas ci-dessus, j'ouvre LoginFragmentlorsque l' Button buttonon appuie sur, en ce moment l'utilisateur est dedans SignupFragment. Donc, si addToBackStack(TAG)est appelé, où TAG = "SignupFragment", puis lorsque le bouton retour est enfoncé LoginFragment, nous revenons à SignUpFragment.

Codage heureux!


Je pense que TAG n'affecte pas, il peut même être nul.
CoolMind

1

En ajoutant fragment_tran.addToBackStack(null) le dernier fragment, je peux revenir sur le dernier fragment.

ajout d'un nouveau fragment :

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });

1

Je suis venu ici à la recherche de la même idée, et en attendant, j'ai trouvé ma propre idée, qui, je crois, n'est pas si mauvaise et fonctionne si avec ViewPager.

Donc, ce que j'ai fait, c'est remplacer la méthode onBackPressed dans l'activité parent qui contient le viewPager, et le configurer pour toujours revenir en arrière de la position 1 jusqu'à ce qu'il atteigne le premier fragment, puis ferme l'activité.

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

Cela peut avoir des inconvénients, comme si cela ne remonte que dans un sens à chaque fois, donc cela pourrait ne pas fonctionner très bien s'il y a des onglets et que vous changez de position avec des fragments ignorés, (passer de 0 à 2, puis appuyer sur en arrière vous mettrait sur 1, au lieu de 0)

Pour mon cas, avec 2 fragments dans viewPager sans onglets, il fait bien le travail.


Une question similaire a déjà été répondue. stackoverflow.com/questions/10863572/…
AtifSayings

0

Essayez le code ci-dessous:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.