2013-02-11 9 views
70

aktywność:android - fragment .replace() nie zastępuje zawartość - umieszcza ją na

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

Fragment1 fragment = new Fragment1(); 
Fragment2 fragment2 = new Fragment2(); 

transaction.replace(R.id.Fragment1, fragment); 
transaction.addToBackStack(null); 
transaction.commit(); 

FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction(); 
transaction2.replace(R.id.Fragment1, fragment2); 
transaction2.addToBackStack(null); 
transaction2.commit(); 

kodu w widoku:

<fragment 
    android:id="@+id/Fragment1" 
    android:name="com.landa.fragment.Fragment1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentLeft="true" 
    android:layout_below="@+id/include1" /> 

problem to, że zawartość nie Naprawdę dostaje się zastąpiony - jest nakładany na wierzch (więc się nakłada).

Kiedy klikam, pierwszy fragment zostanie wyświetlony poprawnie (bez drugiego), ale początkowo oba są widoczne (chcę, aby tylko ostatni był widoczny).

Czego mi tu brakuje?

Odpowiedz

106

Robicie dwie rzeczy źle tutaj:

  1. Nie można zastąpić fragment, który jest statycznie umieszczone w pliku xml układu. Należy utworzyć kontener (np. FrameLayout) w układzie, a następnie dodać ten fragment programowo, używając FragmentTransaction.

  2. FragmentTransaction.replace oczekuje, że jako pierwszy parametr będzie podawany identyfikator kontenera, który zawiera fragment, a nie id fragmentu. Powinieneś przekazać pierwszy argument jako identyfikator kontenera, do którego dodałeś pierwszy fragment.

Więcej informacji można znaleźć pod adresem this link.

+13

Używanie 'FrameLayout' jako kontenera jest lepsze niż użycie' LinearLayout'. –

+1

Korzystanie z pustego FrameLayout w działaniu rozwiązało również mój problem –

+1

Działa to w ten sposób. Ale kiedy uruchomię aplikację i natychmiast naciśniesz przycisk Wstecz, kończę w stanie, w którym fragment jest pusty, zamiast wychodzić z aplikacji? – MasterScrat

3

Można wyczyścić backStack przed fragmentów zastępujących:

FragmentManager fm = getActivity().getSupportFragmentManager(); 

    for (int i = 0; i < fm.getBackStackEntryCount(); i++) { 
     fm.popBackStack(); 
    } 

    // replace your fragments 
+0

problemem jest to, że został ogłoszony w jego fragment pliku XML szablonu. W związku z tym nie można go usunąć/zastąpić w czasie wykonywania. –

+0

to działało dla mnie, próbując zastąpić fragment bez usuwania backstacku, najwyraźniej pozostawiło ostatnie zgłoszenie backstackowe na szczycie dowolnego innego fragmentu. – speedynomads

+0

@Michal Gdzie umieścić ten kod? – Roon13

22

miałem podobny problem, ale moim problemem było to, że używałem dwóch różnych menedżerów Fragmentów: Jeden z getSupportFragmentManager() i jeden z getFragmentManager(). Jeśli dodałem jeden fragment za pomocą SupportFragmentManager, a następnie spróbowałem zastąpić fragment fragmentem FragmentManager, fragment zostałby po prostu dodany na wierzchu. Musiałem zmienić kod, aby ten sam FragmentManager był używany i który zajmował się problemem.

0

Zgadzam się z odpowiedzią Sapana Diwakara. Ale znalazłem obejście tego, jak to zrobić.

Najpierw w swojej aktywności (np. activity_main), w której masz wszystkie układy, Dodaj FrameLayout. Jego wysokość i szerokość powinny wynosić match parent. Nadaj mu także id.

Teraz, w swoim fragmencie, który ma zastąpić obecny układ, zadzwoń pod numer onPause() i onResume(). Zainicjuj wszystkie wewnętrzne pojemniki w View.I ustawić ich visibility do GONE w onResume() i VISIBLE w onPause().

UWAGA: Nie jako FrameLayout, który zastępuje się tym fragmentem.

Załóżmy, że masz ViewPager, TabLayout, ImageView i zwyczaj <fragment> w activity_main.xml. Dodaj, FrameLayout, jak wspomniano powyżej.

W abcFragment.java w onClick() funkcji, dodać addToBackstack(null) w transaction.

Przykładowy kod:

w xyzFragment, który ma zastąpić abcFragment (wszystko pokazane w activity_main.xml), zrób to

@Override 
    public void onResume() { 
     super.onResume(); 

    // On resume, make everything in activity_main invisible except this fragment. 
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs); 
    viewPager = getActivity().findViewById(R.id.pager); 
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager); 

    slidingTabs.setVisibility(View.GONE); 
    viewPager.setVisibility(View.GONE); 
    miniPlayerFragment.setVisibility(View.GONE); 
} 

@Override 
public void onPause() { 
    super.onPause(); 

    // Make everything visible again 
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs); 
    viewPager = getActivity().findViewById(R.id.pager); 
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager); 

    slidingTabs.setVisibility(View.VISIBLE); 
    viewPager.setVisibility(View.VISIBLE); 
    miniPlayerFragment.setVisibility(View.VISIBLE); 
} 

Szczęśliwy kodowania!

0

Dziękuję Sapanowi Diwakarowi i innym. Ta odpowiedź pomogła mi. Po prostu utworzyłem RelativeLayout bez fragmentu wewnątrz niego, użyłem RelativeLayout jako widoku nadrzędnego lub grupowego, określiłem widok grupy w transakcji do zastąpienia i zadziałało.

kod. getSupportFragmentManager() beginTransaction() .replace (R.id.content_group_view, itemDetailFragment) .commit();

Układ:

<RelativeLayout 
     android:id="@+id/content_group_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
</RelativeLayout> 
0

Użyj pojemnika zamiast korzystania fragment

<FrameLayout 
     android:id="@+id/container" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:text="Hello World!" /> 

Teraz w główną działalność

if(condition) 
    getFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit();      
else 
    getFragmentManager().beginTransaction().replace(R.id.container, new SecondFragment()).commit(); 

Należy pamiętać, że klasa fragment powinien importować „android.app. Fragment " Upewnij się, że używasz" support.v4 "lub" original " "implementacje i nie mieszaj ich. Miałem ten problem, ponieważ je wymieszałem.

0

Możesz użyć metody setTransition z FragmentTransaction, aby rozwiązać problem nakładania się.

2

Miałem ten sam problem i widziałem wszystkie odpowiedzi, ale żaden z nich nie zawierał mojego błędu! Przed próbą zastąpienia obecnego fragmentu I pokazywał domyślny fragmentu w xml aktywności pojemnika jak ten:

<FrameLayout 
    android:id="@+id/fragment_frame_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <fragment 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:name="....ShopFragment" 
     android:id="@+id/fragment" 
     tools:layout="@layout/fragment_shop" /> 
</FrameLayout> 

potem chociaż ja mijał frameLayout do fragmentTransaction.replace(), ale miałem dokładny problem. pokazywał drugi fragment na poprzedniej.

Problem stałej przez usunięcie fragmentu z xml i pokazano go programowo w sposobie onCreate() aktywności pojemnik na domyślnej podgląd na początek programu, jak to:

fragmentTransaction = getFragmentManager().beginTransaction(); 
    fragmentTransaction.replace(R.id.fragment_frame_layout,new ShopFragment()); 
    fragmentTransaction.addToBackStack(null); 
    fragmentTransaction.commit(); 

i aktywności xml pojemnik

<FrameLayout 
    android:id="@+id/fragment_frame_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
+0

To samo tutaj. Dzięki!!!! – cesards

0

W onCreate()

BaseFragmentloginpage fragment = new BaseFragmentloginpage(); 
      android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
      fragmentTransaction.replace(R.id.frame, fragment); 
      fragmentTransaction.isAddToBackStackAllowed(); 
      fragmentTransaction.commit(); 

teraz będzie to zawsze domyślny fragment ... jeśli dodać fragment w układzie xml będzie zawsze pokrywają się, więc ustawić początkową zawartość z fragmentu w czasie wykonywania

0

miałem ten sam problem po użyciu tego problemu rozwiązać

  1. Take układ ramki, w której są u ur zastępując fragment

    <FrameLayout 
           android:id="@+id/fragment_place" 
           android:layout_width="match_parent" 
           android:layout_height="match_parent" /> 
    
  2. i kodu wymiany

    public void selectFrag(View view) { 
    Fragment fr; 
    
        if(view == findViewById(R.id.button2)) 
    { 
        fr = new FragmentTwo(); 
    
    }else { 
        fr = new FragmentOne(); 
    } 
    FragmentManager fm = getFragmentManager(); 
    FragmentTransaction fragmentTransaction = fm.beginTransaction(); 
    fragmentTransaction.replace(R.id.fragment_place, fr); 
    fragmentTransaction.commit(); 
    

jeśli chcesz cały przykład ja wyśle ​​po prostu skomentować mnie ......