244 votes

Comment faire en sorte qu'un fragment se supprime lui-même, c'est-à-dire son équivalent de finish() ?

Je suis en train de convertir une application pour utiliser des fragments en utilisant la bibliothèque de compatibilité. Actuellement, j'ai un certain nombre d'activités (A B C D) qui s'enchaînent les unes aux autres, D a un bouton 'OK' qui, lorsqu'il est pressé, appelle finish qui s'élève ensuite dans les bulles de l'application. onActivityResult() pour détruire en plus C et B.

Pour ma version des fragments pré-Honycomb, chaque activité est effectivement une enveloppe sur les fragments Af Bf Cf Df. Toutes les activités sont lancées via startActivityForResult() et onActivityResult() au sein de chacun des fragments peut heureusement appeler getActivity().finish()

Le problème que j'ai cependant est que dans ma version Honeycomb, je n'ai qu'une seule activité, A, et les fragments Bf, Cf, Df sont chargés à l'aide de la fonction de chargement de l'activité. FragmentManager .

Ce que je ne comprends pas, c'est ce qu'il faut faire dans Df lorsque l'on appuie sur "OK" afin de supprimer les fragments Df, Cf et Bf ?

J'ai essayé de faire en sorte que le fragment s'éjecte lui-même de la pile, mais cela a donné lieu à une exception. onActivityResult() est inutile car je n'ai pas chargé le fragment à l'aide de startActivityForResult() .

Est-ce que je pense à ça de la mauvaise façon ? Devrais-je implémenter une sorte d'écouteur qui communique avec le fragment ou l'activité parent afin d'effectuer le pop en utilisant le gestionnaire de transactions ?

7 votes

Qu'en est-il de ((YourActivity) getActivity()).onBackPressed() ;

0 votes

@ViswanathLekshmanan votre commentaire réponse est utile pour moi . 1 Upvote de moi

0 votes

@AbhishekSingh Bon à savoir :)

321voto

Manfred Moser Points 13454

Bien que ce ne soit pas la meilleure approche, l'équivalent le plus proche auquel je pense et qui fonctionne est celui-ci avec la bibliothèque de support/compatibilité.

getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

ou

getActivity().getFragmentManager().beginTransaction().remove(this).commit();

autrement.

En outre, vous pouvez utiliser le backstack et le faire sauter. Cependant, gardez à l'esprit que le fragment peut ne pas se trouver sur la pile arrière (en fonction de la transaction de fragment qui l'y a amené...) ou qu'il peut ne pas être le dernier à s'être retrouvé sur la pile, de sorte que le fait de faire sauter la pile peut retirer le mauvais fragment...

12 votes

Bien que cette approche fonctionne, si vous utilisez addToBackStack(null), le gestionnaire du bouton retour sera laissé à +1. Vous devrez donc appuyer deux fois sur le bouton.

0 votes

Alors pouvez-vous éviter cela d'une manière ou d'une autre ?

34 votes

"pop" le fragment à partir du FragmentManager.

274voto

Eric Yuan Points 1145

Vous pouvez utiliser l'approche ci-dessous, elle fonctionne bien :

getActivity().getSupportFragmentManager().popBackStack();

45 votes

Cette réponse est dix fois meilleure que celle qui a été acceptée - elle va droit au but.

52 votes

Il est également 10 fois pire en termes de conception que celui qui a été accepté. Un fragment est censé être une petite "aide" à une activité et ne devrait jamais avoir le contrôle sur lui-même ou sur d'autres fragments.

6 votes

La solution n'est pas correcte comme l'a souligné @avalancha. Jetez un coup d'œil à developer.Android.com/guide/composants/

67voto

CommonsWare Points 402670

Ce que je ne comprends pas, c'est ce qu'il faut faire dans Df lorsque l'on appuie sur "OK" afin de supprimer les fragments Df, Cf et Bf ?

Etape #1 : Demandez à Df de dire à D "yo ! on a eu le clic OK !" en appelant une méthode, soit sur l'activité elle-même, soit sur une instance d'interface fournie par l'activité.

Étape 2 : Demandez à D de retirer les fragments via FragmentManager .

L'activité d'accueil (D) est celle qui sait quels autres fragments sont dans l'activité (par opposition à ceux qui sont dans d'autres activités). Par conséquent, les événements intra-fragment qui pourraient affecter le mélange de fragments devraient être propagés à l'activité, qui fera les mouvements d'orchestration appropriés.

0 votes

Mais dans ma version Honeycomb il n'y a pas de D, c'est là ma difficulté. Il y a simplement une activité A qui charge le fragment Bf, qui charge Cf, qui charge Df en utilisant FragmentTransaction.

1 votes

@PJL : Désolé, je voulais dire A. C'est l'une des raisons d'utiliser une interface d'écoute, afin que plusieurs activités puissent toutes répondre à l'événement "nous avons reçu le clic OK" de Df.

1 votes

Comme je suis en train de porter, j'ai appelé une méthode d'écoute de la méthode onActivityResult de fragments Df dans l'activité, après quoi j'ai appelé popBackStack sur le FragmentManager. Cependant, cela entraîne une exception "IllegalStateException : Can not perform this action after onSaveInstanceState". Avez-vous une idée de la façon dont je peux résoudre ce problème ?

38voto

Blundell Points 28342

Vous devriez laisser l'activité s'occuper de l'ajout et de la suppression des fragments, comme le dit CommonsWare, utilisez un écouteur. Voici un exemple :

public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {

    // onCreate etc

    @Override
    public void onFragmentSuicide(String tag) {
        // Check tag if you do this with more than one fragmen, then:
        getSupportFragmentManager().popBackStack();
    }
}

public interface SuicidalFragmentListener {
    void onFragmentSuicide(String tag);
}

public class MyFragment extends Fragment {

    // onCreateView etc

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
           suicideListener = (SuicidalFragmentListener) activity;
        } catch (ClassCastException e) {
           throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Attach the close listener to whatever action on the fragment you want
        addSuicideTouchListener();
    }

    private void addSuicideTouchListener() {
        getView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              suicideListener.onFragmentSuicide(getTag());
            }
        });
    }
}

5 votes

Suicide beaucoup de style emo ? Que diriez-vous de "SelfClosing" ou "AutoClose" ou "SmartClose"(r)

21 votes

Ce n'est pas la fermeture, c'est MOURIR POUR TOUJOURS ;-(

3 votes

Cette approche est beaucoup plus propre que les autres réponses. L'activité crée et présente le fragment, et doit contrôler son cycle de vie. Lorsque quelque chose se produit qui indique que le fragment ne devrait plus être visible, elle devrait le dire à l'activité et laisser l'activité le supprimer.

3voto

JayR Points 115

Je pense que si vous voulez renvoyer/finir votre fragment actuel, la meilleure façon de le faire est aussi simple que de faire getFragmentManager().popBackStack() ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X