Fragmen tidak diganti tetapi diletakkan di atas yang sebelumnya

104

Aktivitas:

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

Kode dalam tampilan:

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

Masalahnya adalah, konten tidak benar-benar diganti - konten tersebut diletakkan di atas (sehingga tumpang tindih).

Ketika saya mengklik kembali, fragmen pertama akan ditampilkan dengan benar (tanpa yang kedua), tetapi awalnya keduanya terlihat (saya hanya ingin yang terakhir terlihat).

Apa yang kulewatkan di sini?

Alat
sumber
Dalam kasus saya, masalahnya adalah karena fakta bahwa saya tidak menggunakan id yang sesuai dari tampilan kontainer, yaitu saya tidak memberikan yang benar containerViewId(dalam replacemetode).
nbro

Jawaban:

145

Anda melakukan dua hal yang salah di sini:

  1. Anda tidak dapat mengganti fragmen yang ditempatkan secara statis dalam xmlfile tata letak. Anda harus membuat wadah (mis. A FrameLayout) dalam tata letak dan kemudian menambahkan fragmen secara terprogram FragmentTransaction.

  2. FragmentTransaction.replacemengharapkan id wadah yang berisi fragmen dan bukan id dari fragmen sebagai parameter pertama. Jadi, Anda harus meneruskan argumen pertama sebagai id container tempat Anda menambahkan fragmen pertama.

Anda dapat merujuk ke tautan ini untuk lebih jelasnya.

Sapan Diwakar
sumber
17
Menggunakan FrameLayoutsebagai wadah lebih baik daripada menggunakan LinearLayout.
Marcel Bro
3
Menggunakan FrameLayout kosong dalam Aktivitas memecahkan masalah saya juga
Subtle Fox
1
Ini berhasil melakukan ini. Tetapi kemudian ketika saya memulai aplikasi saya dan segera menekan tombol kembali, saya berakhir dalam keadaan di mana fragmen itu kosong, bukannya keluar dari aplikasi?
MasterScrat
@MasterScrat Abaikan addTobackStack(..)saat pertama kali bertransaksi. Ini akan menghindari penempatan wadah FrameLayout kosong ke tumpukan belakang. Anda masih dapat menavigasi kembali ke fragmen yang Anda tambahkan.
Alex Meuer
Berikut adalah video bagus yang menunjukkan penjelasan Anda. youtube.com/watch?v=EbcdMxAIr54
SQL dan Java Learner
32

Saya memiliki masalah yang sama, tetapi masalah saya adalah saya menggunakan dua manajer Fragmen yang berbeda: Satu dari getSupportFragmentManager()dan satu dari getFragmentManager(). Jika saya menambahkan satu fragmen dengan SupportFragmentManagerdan kemudian mencoba mengganti fragmen dengan FragmentManager, fragmen hanya akan ditambahkan di atas. Saya perlu mengubah kodenya sehingga hal yang sama FragmentManagerakan digunakan dan mengatasi masalah tersebut.

swbandit
sumber
7

Saya memiliki masalah yang sama dan melihat semua jawabannya, tetapi tidak ada yang mengandung kesalahan saya! Sebelum mencoba mengganti fragmen saat ini, saya menunjukkan fragmen default di xml aktivitas container seperti ini:

<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>

setelah itu, meskipun saya melewati FrameLayoutke fragmentTransaction.replace()tetapi saya memiliki masalah yang sebenarnya. itu menunjukkan fragmen kedua di atas yang sebelumnya.

Masalah diperbaiki dengan menghapus fragmen dari xml dan menampilkannya secara terprogram dalam onCreate()metode aktivitas penampung untuk pratinjau default pada awal program seperti ini:

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

dan aktivitas penampung xml:

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

Anda dapat menghapus backStack sebelum mengganti fragmen:

    FragmentManager fm = getActivity().getSupportFragmentManager();

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

    // replace your fragments
Michał Z.
sumber
masalahnya adalah dia telah mendeklarasikan fragmen di file layout xml-nya. Oleh karena itu tidak dapat dilepas / diganti pada saat run-time.
Poonam Anthony
ini berhasil bagi saya, mencoba mengganti sebuah fragmen tanpa membersihkan backstack sepertinya meninggalkan entri backstack terbaru di atas fragmen lainnya.
speedynomads
3
<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:windowBackground">
//Add fragment here
</FrameLayout>

Tambahkan android:background="?android:windowBackground">ke wadah tempat fragmen Anda berada. Dalam kasus saya, saya menambahkan FrameLayout, yang seharusnya membantu.

ralph tashinga nyoni
sumber
1

Gunakan wadah daripada menggunakan fragmen

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

Sekarang di MainActivity

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

Harap diperhatikan bahwa kelas fragmen Anda harus mengimpor 'android.app.Fragment'. Pastikan, Anda menggunakan "support.v4" atau implementasi "asli" dan tidak mencampurnya. Saya mendapatkan masalah ini karena saya telah mencampurnya.

Vikash Kumar Verma
sumber
0

Saya setuju dengan jawaban Sapan Diwakar. Tetapi saya telah menemukan solusi tentang cara melakukan ini.

Pertama, dalam aktivitas Anda (misalnya activity_main), di mana Anda memiliki semua tata letak, Tambahkan a FrameLayout. Tinggi dan lebarnya seharusnya match parent. Juga, berikan id.

Sekarang, di fragmen Anda yang akan menggantikan layout saat ini, panggil onPause()dan onResume(). Inisialisasi semua wadah bagian dalam View. Dan atur visibilityke GONEdalamonResume() dan ke VISIBLEdalamonPause() .

CATATAN : Bukan FrameLayoutyang Anda ganti dengan fragmen ini.

Misalkan Anda memiliki ViewPager, TabLayout, ImageViewdan kebiasaan <fragment>di activity_main.xml. Tambahkan, FrameLayoutseperti yang disebutkan di atas.

Dalam abcFragment.java, di onClick()fungsi, tambahkan addToBackstack(null)di transaction.

Kode contoh:

di xyzFragment, yang akan menggantikan abcFragment (dan semua yang ditampilkan di activity_main.xml), lakukan ini

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

Selamat membuat kode!

TheOnlyAnil
sumber
0

Anda dapat menggunakan metode setTransition dari FragmentTransaction untuk memperbaiki masalah yang tumpang tindih.

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
Lavakush
sumber
0

Dalam Oncreate ()

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

sekarang ini akan selalu menjadi fragmen default Anda ... jika Anda menambahkan fragmen dalam layout xml, itu akan selalu tumpang tindih, jadi setel konten awal dengan fragmen pada waktu proses

Volverine
sumber
0

saya memiliki masalah yang sama setelah menggunakan masalah ini diselesaikan

  1. Ambil tata letak bingkai di mana Anda mengganti fragmen Anda

    <FrameLayout
                    android:id="@+id/fragment_place"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />
  2. dan kode untuk penggantian

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

jika Anda ingin seluruh contoh saya akan mengirimkan Anda komentar saya ......

Sunil
sumber
0

Saya juga mengalami masalah yang sama, tetapi itu karena saya tidak mengubah warna latar belakang fragmen yang saya coba tambahkan ke framelayout saya.

Coba lakukan ini, dengan layout_heightdan layout_widthsetel kematch_parent

Swastik Udupa
sumber
0

Saya pernah mengalami masalah ini dan mengetahui bahwa itu karena saya tidak sengaja menghapus android:backgroundatribut yang hilang pada kode xml Anda. Saya percaya ini berfungsi seperti ketika Anda mengecat dinding, android:backgroundadalah warna dinding itu dan tampilan lain ditempatkan di atas warna dasar itu. Ketika Anda tidak mengecat dinding sebelum memposisikan pandangan Anda, pandangan Anda akan berada di atas apa yang sudah ada di dinding itu, dalam kasus Anda, fragmen Anda yang lain. Tidak tahu apakah itu akan membantu Anda, semoga berhasil.

Miguel Pinheiro
sumber
0

Saya telah mencoba di atas semua kasus dan mencoba memperbaiki masalah tetapi masih belum mendapat solusi. Saya tidak tahu mengapa itu tidak berhasil untuk saya. Saya setuju dengan jawaban di atas karena banyak yang setuju.

Saya hanya menyampaikan jawabannya dan di bawah ini adalah cara yang berhasil untuk saya.

Saya telah menambahkan properti ini android:clickable="true"di atas tata letak induk pada fragment.xmlfile.

Saya berharap seseorang akan mendapatkan bantuan.

Shailesh
sumber
0

Terima kasih untuk Sapan Diwakar dan lainnya. Jawaban ini membantu saya. Saya hanya membuat RelativeLayout tanpa fragmen di dalamnya, menggunakan RelativeLayout sebagai tampilan induk atau grup, menentukan tampilan grup dalam transaksi untuk diganti, dan berhasil.

Kode:

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

XML:

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

 </RelativeLayout>
Craig D
sumber
0

Periksa ID tata letak bingkai Anda dan ganti seperti di bawah ini

fragmentTransactionChange = MainActivity.this.getSupportFragmentManager().beginTransaction();
fragmentTransactionChange.replace(R.id.progileframe, changeFragment);
fragmentTransactionChange.addToBackStack(null);
fragmentTransactionChange.commit();
Sandeep Pareek
sumber