2012-12-07 16 views
29

Jak używać (lub "Czy możemy użyć") getChildFragmentManager() na programowo (dynamicznie) dodano Fragment s?getChildFragmentManager() na programowo (dynamicznie) dodane Fragmenty?

Oto mój przykład.

Mam jeden MainActivity, jeden OuterFrag i jeden InnerFrag. Dodam dynamicznie OuterFrag do MainActivity przez FragmentManager. Ponadto dodam InnerFrag do OuterFrag również dynamicznie przez FragmentManager. Ale chcę dodać InnerFrag dokładnie jako dziecko z OuterFrag, nie zastępując OuterFrag i być nowym dzieckiem z MainActivity.

Chcę zachować tę hierarchię: MainActivity -> OuterFrag -> InnerFrag. Tak więc MainActivity może zawsze wywoływać OuterFrag.

lecz nie zmienia od tej hierarchii: MainActivity -> OuterFrag do tej hierarchii: MainActivity -> InnerFrag że MainActivity woli utraty OuterFrag.

Oto mój przykładowy kod.

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(); 
    } 
} 

outer_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" /> 

Obecnie powyższy kod można uruchomić bez błędów. Ale tak naprawdę zmienia się InnerFrag jako nowe dziecko z MainActivity. Można to zweryfikować za pomocą dwóch instrukcji Wydruki systemowe, które zmieniają Przed: Obiekt i Po: Obiekt. W OuterFrag.java, jeśli sprawozdanie getChildFragmentManager() są uruchamiane zamiast sprawozdania getFragmentManager(), otrzymamy następujący błąd wykonania:

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} 

Korzystanie getChildFragmentManager() jest teoretycznie poprawne. Może być używany w nie programowo dodanym fragmencie (co oznacza zmianę activity_main.xml 's <FrameLayout> na <fragment>, dodanie atrybutu android:name="com.example.frag.OuterFrag" i usunięcie pierwszego oświadczenia getSupportFragmentManager() w MainActivity.java).I zachowuje prawidłową hierarchię: MainActivity -> OuterFrag -> InnerFrag. Ale słowa oryginalnego fragmentu (outer_frag.xml) nigdy nie mogą być usunięte.

Podsumowując, chcę zawsze odwoływać się do OuterFrag w MainActivity. I chcę, aby OuterFrag działał jako symbol zastępczy do ładowania różnych InnerFrag s. Krótko mówiąc, chcę zadzwonić pod numer getChildFragmentManager() w OuterFrag, gdy zostanie dodany programowo (dynamicznie).

+0

Dostałeś tę pracę? Moje pytanie brzmi: kiedy dodasz 'InnerFrag', aby pasował on bezproblemowo do cyklu życia' OuterFrag'? – StuStirling

Odpowiedz

45

In conclusion, I want to reference OuterFrag in MainActivity always. And I want OuterFrag act as a placeholder to load different InnerFrags. In short, I want to call getChildFragmentManager() in OuterFrag, when it is added programmatically (dynamically).

Jeśli chcesz to następnie dokonaj OuterFrag posiada układ pojemnika jak i jego zawartości niezależnie InnerFrag dodać do tego pojemnika. Plik układ dla OuterFrag będą:

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

Oczywiście można mieć inne poglądy w układzie dla OuterFrag jeśli chcemy. Następnie metoda addInnerFrag będą:

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

Kod dodawania OuterFrag do głównej działalności pozostaje ważny.

+1

działa idealnie! Wielkie dzięki! – midnite

+0

Witam @Luksprog postępuję zgodnie z powyższą metodą, a Fragment wewnętrzny został dodany do OuterFragment. Ale OuterFragment nie zastępuje treści. Jest on dodawany jako widok i widoczna jest również poprzednia zawartość w OuterFragment. Próbowałem również przy użyciu ** beginTransaction(). Replace **, ale nie ma zmiany w op. Proszę mi pomóc ................... –

+1

@ KK_07k11A0585 Proszę napisać nowe pytanie, podając więcej szczegółów na temat twojego problemu. Należy pamiętać, że transakcja fragmentu nie zastąpi widoków, które są już w układzie, w którym fragment zostanie dodany. Jeśli chcesz go również zastąpić, wstaw te początkowe widoki do innego fragmentu. – Luksprog

0

Jeśli chcesz zadzwonić addInnerFrag() w kodzie OuterFrag.java, można zrobić to tak:

OuterFrag.java:

@Override 
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    addInnerFrag(); 
} 
Powiązane problemy