Fragmen di ViewPager menggunakan FragmentPagerAdapter kosong saat kedua kali dilihat

98

Saya memiliki antarmuka fragmen dengan tab di sepanjang bagian bawah yang membuka fragmen berbeda di tampilan utama.

Saya memiliki satu fragmen tertentu yang merupakan daftar item. Jika pengguna memilih salah satu item dalam daftar ini, fragmen lain terbuka yang berisi viewpager yang menggulir secara horizontal di antara semua item dalam daftar di fragmen sebelumnya. Ini bekerja dengan baik.

Viewpager menggunakan FragmentPagerAdapter untuk menampilkan item.

Masalahnya muncul saat pengguna memilih item dalam daftar, melihatnya, lalu menekan tombol pada bilah tab untuk kembali ke daftar, lalu memilih item lain. Kedua kalinya item dipilih, layar kosong muncul sebagai ganti viewpager. Saya tidak menerima kesalahan dalam LogCat saya saat ini terjadi.

Mengapa viewpager hanya muncul pertama kali?

FragmentPagerAdapter:

public class ViewPagerAdapter extends FragmentPagerAdapter {
    Cursor mCursor;

    public ViewPagerAdapter(FragmentManager fm, Cursor c) {
        super(fm);
        mCursor = c;
    }

    public void changeCursor(Cursor c) {
        mCursor = c;
        this.notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        if (mCursor == null) return 0;
        else return mCursor.getCount();
    }

    @Override
    public Fragment getItem(int position) {
        mCursor.moveToPosition(position);
        return TeamCardFragment.newInstance(mCursor, position);
    }
}

PagerFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Bundle bundle = getArguments();
    mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);

    View mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);

    mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
    new setAdapterTask().execute();

    return mView;
}

private class setAdapterTask extends AsyncTask<Void, Void, Void> {
    protected Void doInBackground(Void... params) {
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        mViewPager.setAdapter(mAdapter);
        mViewPager.setCurrentItem(mCursorPosition);
    }
}
howettl
sumber

Jawaban:

221

Saya memiliki masalah yang sama. Mengubah kelas induk PageAdapter saya dari android.support.v4.app.FragmentPagerAdapteruntuk android.support.v4.app.FragmentStatePagerAdaptermemecahkan ViewPagermasalah tampilan saya pada "kedua kalinya"!

Yann
sumber
2
Tidak bercanda? Saya tidak memiliki kode ini lagi kalau tidak saya akan mengujinya. Mungkin jawaban ini akan membantu orang lain.
howettl
10
Pria yang luar biasa! Saya sedang mencari solusi ini selama berhari-hari! Terima kasih banyak, bekerja seperti pesona. Tetapi pengembang dalam diri saya bertanya apa dampak perubahan itu? Maksud saya mengapa tidak berhasil sebelumnya dan mengapa di StatePagerAdapter
Anand Sainath
1
Anda juga perlu @Override public int getItemPosition (Object object) {return POSITION_NONE; }
Helin Wang
1
Bekerja untuk saya juga. Ini tautannya. Tampaknya menyimpan status fragmen, yang membuat semua perbedaan. developer.android.com/reference/android/support/v4/app/…
Tjaart
1
Kebetulan ini berhasil, jawaban yang benar adalah @Daniel F. Bagaimanapun, untuk kenyamanan pemberi komentar di sini, perbedaan antara FragmentPagerAdapterdan FragmentStatePagerAdapteryang sebelumnya lebih cocok untuk beberapa halaman, ia mempertahankan semua fragmen dalam memori sehingga memiliki kinerja terbaik pada peralihan halaman, sementara yang terakhir lebih cocok untuk banyak halaman. halaman, itu menghancurkan fragmen, hanya mempertahankan statusnya, itu lebih hemat memori tetapi sedikit lebih lambat pada peralihan halaman.
Cristina De Rito
87

Saya berhasil menyelesaikan ini dengan mengganti getFragmentManager()dengan getChildFragmentManager()di dalam fragmen induk. Fragmen induk ini membuat instance android.support.v4.app.FragmentPagerAdapter untuk memuat fragmen pageable (slideable), yang memerlukan pengelola fragmen dalam konstruktor. Untuk konstruktor ini saya meneruskan nilai kembalian getChildFragmentManager().

Tautan hackbod adalah kuncinya ( https://developer.android.com/about/versions/android-4.2.html#NestedFragments ), yang ditemukan di postingan ini Fragmen dalam Fragmen

Untuk menumpuk fragmen, cukup panggil getChildFragmentManager()Fragmen yang ingin Anda tambahi fragmen. Ini mengembalikan FragmentManager yang bisa Anda gunakan seperti yang biasa Anda lakukan dari aktivitas tingkat atas untuk membuat transaksi fragmen.

Daniel F
sumber
Terima kasih ... saya mengalami masalah serupa saat mencoba mengembalikan tampilan tab geser setelah onresume () yang berisi adaptor fragmentpager ... tutorial yang saya gunakan dari tahun 2016 dan saya masih perlu mengubahnya ke fragmentstatepageradapter untuk mendapatkannya kerja. Seandainya aku tahu MENGAPA.
Nerdy Bunz
jawaban ini menghemat banyak waktu saya. Karena hanya menggunakan FragmentStatePagerAdaptertidak menyelesaikan pertanyaan yang diajukan di sini. bersama dengan FragmentStatePagerAdapterdalam fragmen induk YourAdapter adapter = new YourAdapter (getChildFragmentManager()); harus ditambahkan
MMK
17

bagi saya, saya harus memanggil ini di viewpager saya:

myViewPager.setSaveFromParentEnabled(false);

Saya memiliki masalah di mana viewpager tidak menyegarkan dan yang saya lihat hanyalah layar putih kosong di mana fragmen seharusnya berada. Saya meneruskan getChildFragmentManager tetapi tidak membantu.

j2emanue
sumber
1
Mengapa di dunia ini berhasil? Ini memperbaiki masalah saya tetapi saya tidak tahu mengapa.
ClayHerendeen
Saya menghapusnya dari kode saya sekarang. Manajer fragmen yang menyebabkan masalah. Cobalah beralih antara getchildfragmentmanager dan getfragmentmanager
j2emanue
Saya sudah mencobanya. Saya memiliki Tab bersarang masing-masing dengan ViewPagers yang telah menonaktifkan gesekan. Saya tahu ini adalah desain yang buruk tetapi keinginan klien bukan milik saya. Saya menggunakan childFragmentManager untuk bilah tab tingkat atas. Beralih ke tabbar / viewpager tingkat bawah tampaknya tidak menyelesaikan masalah. Saya kira saya akan tetap menggunakan setSaveFromParentEnabled (false) untuk saat ini karena sudah berfungsi.
ClayHerendeen
Apakah Anda menggunakan pustaka dukungan terbaru
j2emanue
2
Saya menghadapi masalah yang sama dari 2 hari terakhir .. Solusi Anda berhasil untuk saya. terima kasih!
brijexecon
11

Dalam kasus saya yang sangat khusus, saat saya menggunakan CoordinatorLayout dengan AppBarLayout dan ViewPager, yang memecahkannya adalah menghapus android: fitSystemWindows = "true" dari properti xml AppBarLayout saya .

Jangan tanya kenapa. Saya tahu kedengarannya agak konyol dan sepertinya tidak ada korelasi, tetapi baris tunggal inilah satu-satunya yang menyebabkan masalah karena saya sudah menggunakan getChildFragmentManager () di adaptor saya. Saya menghabiskan sepanjang hari men-debug kode saya hanya untuk menemukan ini, jadi saya harap ini menghemat waktu orang lain.

emirua
sumber
3
Ya ampun ... Aku hampir menyerah dengan masalah ini. Anda membuat hari aneh saya! Ya ampun Google, WTF salah dengan AppBarLayout? Saya telah melihat hampir seratus halaman dan menghabiskan banyak waktu untuk debugging mencoba memecahkan masalah ini tanpa hasil. Saya sangat bersyukur akhirnya berhasil menyelesaikan masalah dengan komentar Anda. Terima kasih banyak! PS: Saya sangat putus asa sehingga saya bahkan membuat masalah di AOSP: code.google.com/p/android/issues/… XD
Guillem Roca
Terima kasih atas petunjuknya. Setidaknya itu telah membantu kami dalam menyelesaikan masalah. Sekarang kami mencoba mencari opsi untuk menjadikannya layar penuh
Paresh Mayani
Anda adalah penyelamat! Saya benar-benar tidak mengerti mengapa saya mengalami masalah ini dan masih tidak tahu mengapa itu berhasil!
nandu
10

Saya memiliki masalah yang sama ketika saya mengubah adaptor dari FragmentPagerAdaptermenjadi FragmentStatePagerAdapterdan getFragmentManager()di fragmen induk menjadigetChildFragmentManager()

Alasan di balik ini sangat FragmentStatePagerAdaptermembantu dalam menyimpan sejumlah besar halaman dan memori yang terkait dengan setiap halaman yang dikunjungi lebih sedikit karena hanya menyimpan status fragmen yang disimpan sementara halaman tidak terlihat. Ini mengurangi overhead saat beralih antar fragmen.

NP Yashaswi
sumber
4

Cobalah untuk menempatkan setOffscreenPageLimit (int limit)pada orang tua ViewPager.

mViewPager.setOffscreenPageLimit(totalPages-1);

Ini bekerja untuk saya seperti pesona.

Dalam kasus saya, saya memiliki pecahan di dalamnya TabLayout denganViewPager.

Dan satu lagi ViewPagerdi dalam pecahan itu. Pertama kali semua berfungsi dengan baik tetapi ketika saya mengubah tab dan kembali, beberapa fragmen saya kosong.

Rumit Patel
sumber
1
Jawaban yang bagus. Itu membantu saya.
Thirumalvalavan
2

Ini akan membantumu.

    viewPager.setOffscreenPageLimit(position);
Pardeep Singh
sumber
1

Kami mengatasi ini dengan mengimplementasikan kembali item view pager sebagai tampilan standar, bukan sebagai fragmen, dan mengubah adaptor yang sesuai.

howettl
sumber
Anda dapat mencoba menghapus fungsi isViewFromObject (View view, Object object)
Mina Samy
Pasti ada cara yang lebih baik ....: / meskipun semakin saya menggali Android, saya semakin tidak dewasa.
StackOverflow
1
Fragmen bersarang tidak didukung , jadi menerapkan ulang dengan tampilan standar tampaknya merupakan cara yang tepat.
Sylphe
Saya berjuang dengan masalah serupa. Saya mencoba menggunakan PagerAdapter alih-alih FragmentAdapter, saya masih mengalami masalah yang sama. Tolong bantu saya!
Gaurav Arora
Jika Anda ingin menggunakan fragmen bersarang, Anda dapat menggunakan adaptor yang saya berikan dalam jawaban ini: stackoverflow.com/questions/7700226/…
Slickelito
1

Saya mendapatkan masalah yang sama ini di Xamarin Android dengan layar kosong untuk kedua kalinya .. Pengaturan berikut memperbaikinya untuk saya.

viewPager.SaveFromParentEnabled = false;
Gerard
sumber
0

Anda juga dapat menginisialisasi adaptor jika Anda mengalami error ini saat aplikasi Anda diminimalkan dan kemudian dipanggil.

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Bundle bundle = getArguments();
    mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);
    View mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
    initViewPagerAdapter();
    return mView;
}
private void initViewPagerAdapter(){
    mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
    new setAdapterTask().execute();
}

@Override
public void onResume(){
    super.onResume();
    initViewPagerAdapter();
}
Patrick
sumber
0

Saya memiliki hal yang sama, di saat kedua saya memanggil Adaptor Pager, tampilan anak mengembalikan NullPointerException. Dan mengubah adapder di FragmentStatePagerAdapter juga menyelesaikan masalah saya.

Arka-57
sumber
0

Ubah FragmentPagerAdapterke FragmentStatePagerAdapter Gunakan, getChildFragmentManager()bukangetFragmentManager()

getChildFragmentManager()- karena menurut dokumentasi, ini akan mengembalikan FragmentManager pribadi untuk menempatkan dan mengelola Fragmen di dalam Fragmen ini. Sementara itu getFragmentManager()akan mengembalikan FragmentManager untuk berinteraksi dengan fragmen yang terkait dengan aktivitas ini

Mostafa Anter
sumber
0

class ViewPagerAdapter memperluas FragmentStatePagerAdapter ini berfungsi untuk saya coba ini

Abdul Basit Abbasi
sumber