145 votes

Les Fragments à l'intérieur des Fragments

Je me demande si c'est réellement un bug dans l'API Android:

J'ai une configuration comme suit:

┌----┬---------┐
|    |         |
|  1 |    2    |
|    |┌-------┐|
|    ||       ||
|    ||   3   ||
└----┴┴-------┴┘
  1. Est un menu qui charge fragment n ° 2 (Un écran de recherche) dans le volet de droite.
  2. Est un écran de recherche qui contient le fragment n ° 3, qui est une liste de résultats.
  3. La liste de résultats est utilisée dans plusieurs endroits (y compris un fonctionnement de haut niveau fragment dans son propre droit).

Cette fonctionnalité fonctionne parfaitement bien sur un téléphone (Où 1 & 2 et 3 ActivityFragments).

Cependant, lorsque j'ai utilisé ce code:

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();       
    Fragment frag = new FragmentNumber2();
    if(toLoad != null) frag.setArguments(toLoad);
    transaction.replace(R.id.rightPane, frag);      
    transaction.commit();

R.id.leftPane et R.id.rightPane sont <fragment>s dans un linéaire horizontale de mise en page.

C'est ma compréhension que le code ci-dessus supprime le fragment qui est un résident et puis le remplace par un nouveau fragment. Brillant... Évidemment, ce n'est pas ce qui se passe parce que lorsque ce code est exécuté la deuxième fois que vous obtenez l'exception suivante:

07-27 15:22:55.940: ERROR/AndroidRuntime(8105): Caused by: java.lang.IllegalArgumentException: Binary XML file line #57: Duplicate id 0x7f080024, tag null, or parent id 0x0 with another fragment for FragmentNumber3

Cela est dû au fait que le conteneur pour FragmentNumber3 a été dupliqué et qu'il n'a plus un ID unique. Le Fragment initial n'a pas été détruit (?) avant le nouveau est ajouté (dans mon esprit, cela signifie qu'il n'a pas été remplacé).

Quelqu'un peut-il me dire si cela est possible (cette réponse suggère qu'il n'est pas) ou est-ce un bug?

202voto

hackbod Points 55292

Imbriqués les fragments sont actuellement pas pris en charge. Essaye de mettre un fragment dans l'INTERFACE utilisateur d'un autre fragment entraînera pas défini et probablement cassé comportement.

Mise à jour: Niché fragments sont pris en charge comme d'Android 4.2 (et Android Support Library rev 11) : http://developer.android.com/about/versions/android-4.2.html#NestedFragments

REMARQUE (comme par cette docs): "Note: Vous ne pouvez pas gonfler une mise en page dans un fragment lorsqu'qui comprend une mise en page <fragment>. Imbriqués les fragments ne sont pris en charge lorsqu'il est ajouté à un fragment de façon dynamique."

98voto

Raneez Ahmed Points 1340

Imbriqués les fragments sont pris en charge dans android 4.2 et versions ultérieures

Le Android Support Library supporte également imbriqués fragments, de sorte que vous pouvez mettre en œuvre imbriquée fragment de dessins sur Android 1.6 et supérieur.

Pour imbriquer un fragment, il suffit d'appeler getChildFragmentManager() sur le Fragment dans lequel vous souhaitez ajouter un fragment. Cette fonction retourne une FragmentManager que vous pouvez utiliser comme vous le faites normalement à partir du haut niveau d'activité pour créer un fragment de transactions. Pour exemple, voici un code qui ajoute un fragment de l'intérieur d'un Fragment de la classe:

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

Pour obtenir plus d'idée en ce qui concerne l'imbrication des fragments, s'il vous plaît aller à travers ces tutoriels
Partie 1
Partie 2
Partie 3

et voici un post qui discuter à propos de les meilleures pratiques pour imbriquée fragments.

33voto

furykid Points 568

.. vous pouvez nettoyer votre imbriquée fragment dans le parent du fragment destroyview méthode:

@Override
    public void onDestroyView() {

      try{
        FragmentTransaction transaction = getSupportFragmentManager()
                .beginTransaction();

        transaction.remove(nestedFragment);

        transaction.commit();
      }catch(Exception e){
      }

        super.onDestroyView();
    }

14voto

draksia Points 882

J'ai une application que je développe est disposé similaire avec des Onglets dans la Barre d'Action qui lance des fragments, certains de ces Fragments ont plusieurs des Fragments inclus dans eux.

J'avais la même erreur quand j'essaye d'exécuter l'application. Il semble comme si vous instancier les Fragments dans le xml de mise en page après un onglet a été désactivée et puis resélectionnés je voudrais obtenir le gonfleur d'erreur.

J'ai résolu ce problème en remplaçant tous les fragments xml avec Linearlayouts puis utilisez un Fragment de manager/ fragment de transaction pour instancier les fragments tout semble fonctionner correctement à au moins un test de niveau en ce moment.

J'espère que cela vous aide.

4voto

ievgen Points 118

J'ai été confronté au même problème, ont lutté quelques jours avec elle et dire que le plus simple pour surmonter j'ai trouvé c'est d'utiliser le fragment.hide() / fragment.show() lorsque l'onglet est activée/désactivée().

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
{
    if (mFragment != null)
        ft.hide(mFragment);
}

Lors de la rotation de l'écran se produit tous les parents et l'enfant les fragments sont correctement détruits.

Cette approche a également un avantage supplémentaire - à l'aide de hide () et show() ne cause pas de fragment de vues à perdre de leur état, donc il n'est pas nécessaire de restaurer la version précédente, la position de défilement pour ScrollViews par exemple.

Le problème est que je ne sais pas si c'est correct de ne pas se détacher des fragments quand ils ne sont pas visibles. Je pense que les officiels exemple de TabListener est conçu avec une pensée dans l'esprit que les fragments sont réutilisables et vous ne devriez pas polluer avec leur mémoire, cependant, je pense que si vous avez juste quelques onglets et vous savez que les utilisateurs vont être de commutation entre eux fréquemment, il sera approprié pour les garder attachés à l'activité en cours.

J'aimerais entendre les commentaires de plus de développeurs expérimentés.

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