web-dev-qa-db-fra.com

Fragment addToBackStack () et popBackStackImmediate () ne fonctionnent pas

Je suis en train de créer une application pour Android (14 <= ​​SDK <= 21) en utilisant une variable ActionBarActivity et plusieurs Fragments, telles que ListFragment et MapFragment, qui sont échangées dans une seule vue FrameLayout.

ActionBarActivity remplace/valide automatiquement le fragment A. Lorsque l'utilisateur appuie sur un bouton, l'activité d'hébergement remplace/valide un nouveau fragment B. Mon objectif est de permettre à l'utilisateur de revenir sur le fragment A dès qu'elle appuie sur le bouton Précédent. .

Certains code maintenant.

Activité principale

public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener,
    StopItemFragment.OnFragmentInteractionListener {
...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentManager = getFragmentManager();
        fragmentManager.enableDebugLogging(true);
        ...
        if (fragmentManager.findFragmentById(R.id.content_frame) == null) {
            StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
            fragmentManager.beginTransaction()
                .replace(R.id.content_frame, list)
                .addToBackStack(null)
                .commit();
        }
        ...

        @Override
        public void onFragmentInteraction(String id) {
        selectItem(Integer.parseInt(id));
        }


       private void selectItem(int position) {
       StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
       ...
       fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment)
            .commit();

       ...
       }
}


Problème

Même si addToBackStack() est appelé, lorsque je suis sur le fragment B, je ne peux pas revenir au fragment A. MainActivity est directement fermé . Pourtant, j’ai essayé de gérer la pile arrière sans succès. Je peux voir que le fragment est sur la pile, mais si j'appelle popBackStackImmediate(), le fragment A est affiché et la transaction de fragment n'est pas effectuée. (première presse rien ne se passe, deuxième activité fermée)

J'attache également le logcat FragmentManager:
http://Pastebin.com/hFLHprL8

24
Emanuele

Pour ceux qui cherchent encore une solution.

Dans la classe principale Activity (qui héberge les fragments), remplacez simplement onBackPressed().

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

Il n'y a pas de méthode onBackPressed() dans le fragment, et cette méthode est juste pour le activity. Ainsi, lorsque nous appuyons sur la touche Retour, le comportement par défaut de activity est affiché, ce qui est

vous irez à l'activité précédente (s'il y en a une) ou à l'application va sortir.

Nous devons maintenant surcharger cette méthode pour indiquer à la activity que lorsque nous appuierons sur la touche Précédent, s'il reste des fragments dans la pile arrière, les extraire (et c'est ici que la fonction addToBackStack() apparaît). Sinon, suivez le comportement par défaut.

70
Nicks

Essayez ceci (Remarque add pas remplacez pour fragmentA et addToBackStack () pour fragmentB)

StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
        fragmentManager.beginTransaction()
            .add(R.id.content_frame, list)
            .commit();

et

StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
   ...
   fragmentManager.beginTransaction()
        .replace(R.id.content_frame, fragment)
        .addToBackStack("FragmentB")
        .commit();
5
unchosen

J'ai dû appeler beginTransaction() et commit() de FragmentManager manuellement.
Résolu en surchargeant onBackPressed():

@Override
public void onBackPressed() {
    ...
    if (fragmentManager.getBackStackEntryCount() > 1){
        fragmentManager.popBackStackImmediate();
        fragmentManager.beginTransaction().commit();
    } else {
        //handle finish
        finish(); // Closes app
    }
}
5
Emanuele

Si vous vous battez avec addToBackStack () & popBackStack (), utilisez simplement

FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`

Dans votre activité dans OnBackPressed (), recherchez le segment par tag puis faites votre travail

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

if (home instanceof HomeFragment && home.isVisible()) {
    // do you stuff
}

Pour plus d'informations https://github.com/DattaHujare/NavigationDrawer Je n'utilise jamais addToBackStack () pour gérer les fragments.

1
Dattu Hujare

la raison pour laquelle les fonctions popBackStack() et popBackStackImmediatly() est due au fait que vous n'avez pas ajouté ce fragment (que vous souhaitez afficher) à la pile de sauvegarde. Pour ce faire, vous devez appeler addToBackStack () au moment de la transaction pour ajouter/remplacer votre fragment.

0
Pablo Johnson