web-dev-qa-db-fra.com

getChildFragmentManager () sur les fragments ajoutés par programme (dynamiquement)?

Comment utiliser (ou "Pouvons-nous utiliser") getChildFragmentManager() sur des programmes programmés (dynamiquement) ajoutés Fragments?

Voici mon exemple.

J'ai un MainActivity, un OuterFrag et un InnerFrag. Je vais ajouter le OuterFrag à MainActivity dynamiquement par le FragmentManager. Et aussi, j'ajouterai le InnerFrag au OuterFrag aussi dynamiquement par le FragmentManager. Mais je veux ajouter InnerFrag exactement comme un enfant du OuterFrag, sans remplacer OuterFrag et être le nouvel enfant du MainActivity.

Je veux garder cette hiérarchie: MainActivity -> OuterFrag -> InnerFrag. Ainsi, MainActivity peut toujours appeler OuterFrag.

Mais PAS changer de cette hiérarchie: MainActivity -> OuterFrag À cette hiérarchie: MainActivity -> InnerFrag Que MainActivity perdra le OuterFrag.

Voici mon exemple de code.

MainActivity.Java

package com.example.frag;

import Android.os.Bundle;
import Android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {

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

        getSupportFragmentManager().beginTransaction().add(R.id.frameLayout, new OuterFrag()).commit();
        getSupportFragmentManager().executePendingTransactions();

        System.out.println("Before: "
                + getSupportFragmentManager().findFragmentById(R.id.frameLayout));

        ((OuterFrag) getSupportFragmentManager().findFragmentById(R.id.frameLayout))
                .addInnerFrag();

        System.out.println("After: "
                + getSupportFragmentManager().findFragmentById(R.id.frameLayout));
    }
}

activity_main.xml

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/frameLayout"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent" >
</FrameLayout>

OuterFrag.Java

package com.example.frag;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class OuterFrag extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.outer_frag, container, false);
    }

    public void addInnerFrag() {

        getFragmentManager().beginTransaction().replace(this.getId(), new InnerFrag()).commit();
        getFragmentManager().executePendingTransactions();

//        getChildFragmentManager().beginTransaction().add(this.getId(), new InnerFrag()).commit();
//        getChildFragmentManager().executePendingTransactions();
    }
}

externe_frag.xml

<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/textView1"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="i am the OUTER frag" />

InnerFrag.Java

package com.example.frag;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class InnerFrag extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.inner_frag, container, false);
    }
}

inner_frag.xml

<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/textView2"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="i am the INNER frag" />

Actuellement, le code ci-dessus peut s'exécuter sans erreur. Mais cela change en fait InnerFrag en tant que nouvel enfant de MainActivity. Cela peut être vérifié par les deux instructions System Print Out que l'objet Before: Object et After: Object est modifié. Dans OuterFrag.Java, Si les instructions getChildFragmentManager() sont exécutées au lieu des instructions getFragmentManager(), nous obtiendrons l'erreur d'exécution suivante:

12-07 02:29:38.406: E/AndroidRuntime(12051): Java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.frag/com.example.frag.MainActivity}: Java.lang.IllegalArgumentException: No view found for id 0x7f070000 (com.example.frag:id/frameLayout) for fragment InnerFrag{46e32748 #0 id=0x7f070000}

L'utilisation de getChildFragmentManager() est théoriquement correcte. Il peut être utilisé dans un fragment non programmé ajouté (ce qui signifie changer le activity_main.xml De <FrameLayout> En <fragment>, Ajouter l'attribut Android:name="com.example.frag.OuterFrag" Et supprimer le premier getSupportFragmentManager() instruction dans MainActivity.Java). Et il garde la bonne hiérarchie: MainActivity -> OuterFrag -> InnerFrag. Mais les mots du fragment original (outer_frag.xml) Ne peuvent jamais être enlevés.

En conclusion, je veux toujours référencer OuterFrag dans MainActivity. Et je veux que OuterFrag agisse comme un espace réservé pour charger différents InnerFrags. En bref, je veux appeler getChildFragmentManager() dans OuterFrag, quand il est ajouté par programme (dynamiquement).

29
midnite

En conclusion, je veux toujours faire référence à OuterFrag dans MainActivity. Et je veux qu'OuterFrag agisse comme un espace réservé pour charger différents InnerFrags. En bref, je veux appeler getChildFragmentManager () dans OuterFrag, lorsqu'il est ajouté par programme (dynamiquement).

Si vous le souhaitez, faites en sorte que votre OuterFrag ait une disposition de conteneur comme contenu et ajoutez ce que InnerFrag à ce conteneur. Le fichier de mise en page pour le OuterFrag sera:

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/fragContainer"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
/>

Bien sûr, vous pouvez avoir d'autres vues dans la mise en page pour le OuterFrag si vous le souhaitez. Votre méthode addInnerFrag sera alors:

public void addInnerFrag() {
        getChildFragmentManager().beginTransaction().add(R.id.fragContainer, new InnerFrag()).commit();
        getChildFragmentManager().executePendingTransactions();
}

Le code pour ajouter le OuterFrag à l'activité principale reste valide.

45
Luksprog