web-dev-qa-db-fra.com

Android: retour au fragment précédent dans la presse arrière

J'ai implémenté Navigation Drawer, qui est une sous-classe de Activity. J'ai beaucoup de fragments dans ma candidature. Ma question va ici

Imaginez il y a 3 fragments:

Fragment_1: Fragment_2: Fragment_3

Lorsque je lance mon application, Fragment_1 est chargé Lorsque je clique sur certains composants de Fragment_1, je suis dirigé vers Fragment_2 et ainsi de suite.

Donc c'est comme

Fragment_1> Fragment_2> Fragment_3

Lorsque j'appuie sur la touche retour de Fragment_2, je suis redirigé vers Fragment_1 Mais lorsque j'appuie sur la touche retour de Fragment_3, je suis redirigé vers Fragment_1 (au lieu de Fragment_2).

Je veux quelque chose comme ça dans mon application sur la touche Back Key

Fragment_1 <Fragment_2 <Fragment_3

J'ai utilisé Fragment, FragmentManager, FragmentTransaction comme suit: 

MyFragment fragment = new MyFragment();
FragmentManager fragmentManager = getFragmentManager();

fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null)commit();

et j'ai essayé de remplacer onBackPressed () dans MainActivity:

@Override
public void onBackPressed() {


        getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        int count = getFragmentManager().getBackStackEntryCount();
        if (count == 0)
               super.onBackPressed();
    }
18
Hvn

Mettez à jour votre méthode Activity#onBackPressed() pour:

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

La raison pour laquelle votre implémentation ne fonctionne pas, c'est parce que la méthode FragmentManager#popBackStack() est asynchrone et ne se produit pas juste après son appel.

De la documentation:

Cette fonction est asynchrone - elle met la demande à mettre en file d'attente, mais l'action ne sera pas exécutée tant que l'application ne retournera pas à sa boucle d'événements.

Référence: http://developer.Android.com/reference/Android/app/FragmentManager.html#popBackStack(Java.lang.String,%20int)

34
Leandro

Vous devez implémenter votre propre implémentation de backstack comme expliqué ici

Séparez la pile arrière pour chaque onglet dans Android à l'aide de Fragments

Vous pouvez appeler popFragments () à chaque fois que vous cliquez sur le bouton Précédent d'un fragment et appeler pushFragments () lorsque vous naviguez d'un fragment à l'autre.

en bref,

public void onBackPressed()
{
    FragmentManager fm = getActivity().getSupportFragmentManager();
    fm.popBackStack();
}
3
sam

Le tric est en FragmentManager#executePendingTransactions();.

C'est ce que j'utilise aussi pour les fragments imbriqués ...:

/**
 * if there is a fragment and the back stack of this fragment is not empty,
 * then emulate 'onBackPressed' behaviour, because in default, it is not working.
 *
 * @param fm the fragment manager to which we will try to dispatch the back pressed event.
 * @return {@code true} if the onBackPressed event was consumed by a child fragment, otherwise
 */
public static boolean dispatchOnBackPressedToFragments(FragmentManager fm) {

    List<Fragment> fragments = fm.getFragments();
    boolean result;
    if (fragments != null && !fragments.isEmpty()) {
        for (Fragment frag : fragments) {
            if (frag != null && frag.isAdded() && frag.getChildFragmentManager() != null) {
                // go to the next level of child fragments.
                result = dispatchOnBackPressedToFragments(frag.getChildFragmentManager());
                if (result) return true;
            }
        }
    }

    // if the back stack is not empty then we pop the last transaction.
    if (fm.getBackStackEntryCount() > 0) {
        fm.popBackStack();
        fm.executePendingTransactions();
        return true;
    }

    return false;
}

et dans ma onBackPressed:

                if (!FragmentUtils.dispatchOnBackPressedToFragments(fm)) {
                    // if no child fragment consumed the onBackPressed event,
                    // we execute the default behaviour.
                    super.onBackPressed();
                }
2
ahmed_khan_89

Voici le code de travail et testé par moi, cela vous aidera

 private static final int TIME_INTERVAL = 2000;
private long mBackPressed;
 private void applyExit() {
    if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
        finish();
    } else {
         Toast.makeText(this,"Press Again to exit",Toast.LENGTH_LONG).show();
    }
    mBackPressed = System.currentTimeMillis();
}

@Override
public void onBackPressed() {
    fm = getSupportFragmentManager();
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    }
    if (fm.getFragments().size() <= 1) {
        applyExit();
    } else {
        for (Fragment frag : fm.getFragments()) {
            if (frag == null) {
                applyExit();
                return;
            }
            if (frag.isVisible()) {
                FragmentManager childFm = frag.getChildFragmentManager();
                if (childFm.getFragments() == null) {
                    super.onBackPressed();
                    return;
                }
                if (childFm.getBackStackEntryCount() > 0) {
                    childFm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    return;
                } else {
                    fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                    return;
                }
            }
        }
    }
}
0
Ness Tyagi

Utilisez ce code sur l'onglet de changement dans votre activité principale pour effacer la pile.

int count = getFragmentManager().getBackStackEntryCount();
        if(count>0){
            for (int i = 0; i <count; i++) {
                getFragmentManager().popBackStack();
            }
        }

Puis sur Retour appuyé de votre activité principale faire ceci

 int count = getFragmentManager().getBackStackEntryCount();

     if (count == 0) {
         super.onbackpressed();
        }
else {
        getFragmentManager().popBackStack();
    }
 }
0
Nanda