Masalah: Fragmen onResume()
dalam ViewPager
dipecat sebelum fragmen menjadi benar-benar terlihat.
Sebagai contoh, saya punya 2 fragmen dengan ViewPager
dan FragmentPagerAdapter
. Fragmen kedua hanya tersedia untuk pengguna yang berwenang dan saya harus meminta pengguna untuk masuk ketika fragmen menjadi terlihat (menggunakan dialog peringatan).
TETAPI ViewPager
menciptakan fragmen kedua ketika yang pertama terlihat untuk men-cache fragmen kedua dan membuatnya terlihat ketika pengguna mulai menggesek.
Jadi onResume()
acara tersebut dipecat dalam fragmen kedua jauh sebelum terlihat. Itu sebabnya saya mencoba untuk menemukan suatu peristiwa yang menyala ketika fragmen kedua menjadi terlihat untuk menampilkan dialog pada saat yang tepat.
Bagaimana ini bisa dilakukan?
ViewPager
. Dalam pager dua halaman, kedua halaman akan segera dimuat, apakah Anda suka atau tidak. Pengalaman penggunaViewPager
seharusnya adalah bahwa konten ada di sana segera setelah digesek, tidak beberapa waktu kemudian. Itulah sebabnyaViewPager
menginisialisasi halaman di depan apa yang terlihat, untuk membantu memastikan pengalaman pengguna.Jawaban:
Anda dapat melakukan hal berikut dengan menimpa
setUserVisibleHint
diFragment
:sumber
isResumed()
untuk menghindari NPE. Bekerja dengan baik untukku.setUserVisibleHint
sekarang sudah tidak digunakan lagiPEMBARUAN : Pustaka Dukungan Android (rev 11) akhirnya memperbaiki masalah petunjuk yang terlihat oleh pengguna , sekarang jika Anda menggunakan pustaka dukungan untuk fragmen, maka Anda dapat dengan aman menggunakan
getUserVisibleHint()
atau menggantisetUserVisibleHint()
untuk menangkap perubahan seperti dijelaskan oleh jawaban gorn.PEMBARUAN 1 Ini adalah satu masalah kecil dengan
getUserVisibleHint()
. Nilai ini secara defaulttrue
.Jadi mungkin ada masalah ketika Anda mencoba menggunakannya sebelum
setUserVisibleHint()
dipanggil. Sebagai solusinya Anda dapat menetapkan nilai dalamonCreate
metode seperti ini.Jawaban yang kedaluwarsa:
Dalam kebanyakan kasus penggunaan,
ViewPager
hanya menampilkan satu halaman pada satu waktu, tetapi fragmen pra-cache juga dihukum "terlihat" negara (sebenarnya tak terlihat) jika Anda menggunakanFragmentStatePagerAdapter
dalamAndroid Support Library pre-r11
.Saya menimpa:
Untuk menangkap keadaan fokus fragmen, yang saya pikir adalah keadaan yang paling cocok dari "visibilitas" yang Anda maksud, karena hanya satu fragmen di ViewPager yang benar-benar dapat menempatkan item menu bersama dengan item aktivitas induk.
sumber
true
untuk getUserVisibleHint () ketikaonCreateOptionsMenu
dipanggil, dan ketikasetUserVisibleHint
dipanggil, menu belum dibuat sepertinya. Akhirnya saya mendapatkan dua opsi Menu yang ditambahkan ketika saya hanya ingin menu dari fragmen yang terlihat. Ada saran dalam hal ini?setUserVisibleHint
sekarang sudah tidak digunakan lagiIni tampaknya mengembalikan
onResume()
perilaku normal yang Anda harapkan. Itu bermain dengan baik dengan menekan tombol home untuk meninggalkan aplikasi dan kemudian memasukkan kembali aplikasi.onResume()
tidak dipanggil dua kali berturut-turut.sumber
setUserVisibleHint
dipanggil sebelumnyaonCreateView
dan itusetUserVisibleHint
tidak dipanggil jika aplikasi berjalan latar dan kemudian latar depan. Luar biasa! Terima kasih!onVisibleToUser()
metode yang sederhana dan memanggil itu darionResume()
dan darisetUserVisibleHint(boolean)
alih-alih memanggilonResume()
diri saya dan mengganggu callback daur hidup. Kalau tidak, saya pikir pendekatan ini bekerja dengan baik, terima kasih!Berikut cara lain menggunakan
onPageChangeListener
:sumber
setUserVisibleHint()
dipanggil kadang-kadang sebelumonCreateView()
dan kadang-kadang setelah yang menyebabkan masalah.Untuk mengatasinya Anda perlu memeriksa
isResumed()
jugasetUserVisibleHint()
metode di dalam . Tetapi dalam hal ini saya menyadarisetUserVisibleHint()
dipanggil hanya jika Fragmen dilanjutkan dan terlihat, BUKAN saat Dibuat.Jadi, jika Anda ingin memperbarui sesuatu ketika Fragment berada
visible
, masukkan fungsi pembaruan Anda dionCreate()
dansetUserVisibleHint()
:UPDATE: Masih saya menyadari
myUIUpdate()
dipanggil dua kali kadang-kadang, alasannya adalah, jika Anda memiliki 3 tab dan kode ini ada di tab ke-2, ketika Anda pertama kali membuka tab ke-1, tab ke-2 juga dibuat meskipun tidak terlihat danmyUIUpdate()
dipanggil. Kemudian ketika Anda menggeser ke tab ke-2,myUIUpdate()
dariif (visible && isResumed())
dipanggil dan sebagai hasilnya,myUIUpdate()
dapat dipanggil dua kali dalam satu detik.Yang lain masalah adalah
!visible
disetUserVisibleHint
dipanggil kedua 1) ketika Anda pergi keluar dari layar fragmen dan 2) sebelum diciptakan, ketika Anda beralih ke layar fragmen pertama kalinya.Larutan:
Penjelasan:
fragmentResume
,fragmentVisible
: MemastikanmyUIUpdate()
dionCreateView()
disebut hanya ketika fragmen dibuat dan terlihat, tidak di resume. Ini juga memecahkan masalah ketika Anda berada di tab ke-1, tab ke-2 dibuat bahkan jika itu tidak terlihat. Ini menyelesaikan itu dan memeriksa apakah layar fragmen terlihat saatonCreate
.fragmentOnCreated
: Memastikan fragmen tidak terlihat, dan tidak dipanggil saat Anda membuat fragmen pertama kali. Jadi sekarang ini jika klausa hanya dipanggil ketika Anda menggesek fragmen.Pembaruan Anda dapat memasukkan semua kode ini dalam
BaseFragment
kode seperti ini dan mengganti metode.sumber
setUserVisibleHint
tidak mendapat panggilan .. ! dan di dalamonCreateView
metodefragmentVisible
itufalse
!? jadi fragmen itu muncul kosong ..! ada pemikiran.?Untuk mendeteksi
Fragment
dalamViewPager
terlihat, aku cukup yakin bahwa hanya menggunakansetUserVisibleHint
tidak cukup.Inilah solusi saya untuk memeriksa apakah sebuah fragmen terlihat atau tidak terlihat. Pertama saat meluncurkan viewpager, beralih di antara halaman, pergi ke aktivitas / fragmen / latar belakang / latar depan lain`
PENJELASAN Anda dapat memeriksa logcat di bawah ini dengan hati-hati maka saya pikir Anda mungkin tahu mengapa solusi ini akan berhasil
Peluncuran pertama
Pergi ke halaman2
Pergi ke halaman3
Pergi ke latar belakang:
Pergi ke latar depan
Proyek DEMO di sini
Semoga ini bisa membantu
sumber
SubChildContainerFragment
digunakan untuk mendeteksia fragment has another view pager which also consists fragment
. Anda dapat mencampurSubChildContainerFragment
danChildContainerFragment
ke 1 kelas. Semoga ini bisa membantu. Saya akan mengirimkan jawaban lengkapnya nantisumber
setUserVisibleHint
Tidak digunakan lagiDi
ViewPager2
danViewPager
dari versi,androidx.fragment:fragment:1.1.0
Anda bisa menggunakanonPause
danonResume
menelepon balik untuk menentukan fragmen mana yang saat ini terlihat oleh pengguna.onResume
panggilan balik dipanggil saat fragmen menjadi terlihat danonPause
ketika berhenti untuk terlihat.Dalam kasus ViewPager2 itu adalah perilaku default tetapi perilaku yang sama dapat diaktifkan untuk barang lama
ViewPager
dengan mudah.Untuk mengaktifkan perilaku ini di ViewPager pertama Anda harus melewati
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
parameter sebagai argumen keduaFragmentPagerAdapter
konstruktor.Catatan:
setUserVisibleHint()
metode danFragmentPagerAdapter
konstruktor dengan satu parameter sekarang tidak digunakan lagi dalam versi baru Fragment dari android jetpack.sumber
Override
setPrimaryItem()
dalamFragmentPagerAdapter
subclass. Saya menggunakan metode ini, dan itu bekerja dengan baik.sumber
Ganti
Fragment.onHiddenChanged()
untuk itu.sumber
Saya menemukan itu
onCreateOptionsMenu
danonPrepareOptionsMenu
metode yang disebut hanya dalam kasus fragmen benar-benar terlihat. Saya tidak dapat menemukan metode yang berperilaku seperti ini, saya juga mencobaOnPageChangeListener
tetapi tidak berfungsi untuk situasi, misalnya, saya perlu variabel yang diinisialisasi dalamonCreate
metode.Jadi kedua metode ini dapat digunakan untuk masalah ini sebagai solusi, khususnya untuk pekerjaan kecil dan pendek.
Saya pikir, ini adalah solusi yang lebih baik tetapi bukan yang terbaik. Saya akan menggunakan ini tetapi menunggu solusi yang lebih baik pada saat yang sama.
Salam.
sumber
Solusi lain yang diposting di sini mengesampingkan setPrimaryItem di pageradapter oleh kris larson hampir berhasil untuk saya. Tetapi metode ini disebut beberapa kali untuk setiap pengaturan. Saya juga mendapatkan NPE dari pandangan, dll. Dalam fragmen karena ini tidak siap beberapa kali pertama metode ini disebut. Dengan perubahan berikut ini berhasil bagi saya:
sumber
Tambahkan Kode berikut di dalam fragmen
sumber
Saya mengalami masalah yang sama saat bekerja dengan
FragmentStatePagerAdapters
dan 3 tab. Saya harus menunjukkan Dilaog setiap kali tab pertama diklik dan menyembunyikannya saat mengklik tab lain.Mengesampingkan
setUserVisibleHint()
sendiri tidak membantu menemukan fragmen yang terlihat saat ini.Saat mengklik dari tab ke-3 -----> tab ke-1. Ini memicu dua kali untuk fragmen ke-2 dan untuk fragmen ke-1. Saya menggabungkannya dengan metode isResumed ().
sumber
Kami memiliki kasus khusus dengan MVP di mana fragmen perlu memberi tahu presenter bahwa pandangan telah menjadi terlihat, dan presenter disuntikkan oleh Dagger pada
fragment.onAttach()
.setUserVisibleHint()
tidak cukup, kami telah mendeteksi 3 kasus berbeda yang perlu ditangani (onAttach()
disebutkan agar Anda tahu kapan presenter tersedia):Fragmen baru saja dibuat. Sistem membuat panggilan berikut:
Fragmen sudah dibuat dan tombol beranda ditekan. Saat mengembalikan aplikasi ke latar depan, ini disebut:
Perubahan orientasi:
Kami hanya ingin petunjuk visibilitas sampai ke presenter satu kali, jadi ini adalah bagaimana kami melakukannya:
sumber
Mendeteksi oleh
focused view
!Ini bekerja untuk saya
sumber
Saya mengalami masalah ini ketika saya mencoba untuk menyalakan timer ketika fragmen di viewpager berada di layar untuk dilihat oleh pengguna.
Penghitung waktu selalu dimulai tepat sebelum fragmen dilihat oleh pengguna. Ini karena
onResume()
metode dalam fragmen dipanggil sebelum kita dapat melihat fragmen.Solusi saya adalah melakukan pemeriksaan dalam
onResume()
metode ini. Saya ingin memanggil metode tertentu 'foo ()' ketika fragmen 8 adalah pager tampilan saat ini.Semoga ini membantu. Saya telah melihat masalah ini muncul banyak. Ini tampaknya menjadi solusi paling sederhana yang pernah saya lihat. Banyak yang lain tidak kompatibel dengan API yang lebih rendah dll.
sumber
Saya memiliki masalah yang sama.
ViewPager
mengeksekusi peristiwa siklus hidup fragmen lainnya dan saya tidak bisa mengubah perilaku itu. Saya menulis pager sederhana menggunakan fragmen dan animasi yang tersedia. SimplePagersumber
Saya menggunakan ini dan itu berhasil!
sumber
Saya mendukung SectionsPagerAdapter dengan fragmen anak jadi setelah banyak sakit kepala saya akhirnya mendapatkan versi yang berfungsi berdasarkan solusi dari topik ini:
sumber
Catatan yang
setUserVisibleHint(false)
tidak dipanggil pada penghentian aktivitas / fragmen. Anda masih perlu memeriksa mulai / hentikan untukregister/unregister
mendengarkan dengan benar pendengar / dll.Juga, Anda akan mendapatkan
setUserVisibleHint(false)
jika fragmen Anda mulai dalam keadaan tidak terlihat; Anda tidak ingin keunregister
sana karena Anda belum pernah mendaftar sebelumnya dalam kasus itu.sumber
Cara sederhana untuk mengimplementasikannya adalah memeriksa apakah pengguna masuk sebelumnya masuk ke fragmen.
Di MainActivity Anda, Anda dapat melakukan sesuatu seperti ini di dalam metode onNavigationItemSelected .
Namun, jika Anda menggunakan laci navigasi, pilihan dalam laci akan berubah menjadi Profil meskipun kami belum pergi ke ProfileFragment.
Untuk mengatur ulang pilihan ke pilihan saat ini jalankan kode di bawah ini
sumber
setUserVisibleHint (boolean terlihat) sekarang sudah usang Jadi ini adalah solusi yang benar
Di ViewPager2 dan ViewPager dari versi
androidx.fragment:fragment:1.1.0
Anda bisa menggunakanonPause()
danonResume()
untuk menentukan fragmen mana yang saat ini terlihat oleh pengguna.onResume()
disebut ketika fragmen menjadi terlihat danonPause
ketika berhenti untuk terlihat.Untuk mengaktifkan perilaku ini di ViewPager pertama Anda harus melewati
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
parameter sebagai argumen keduaFragmentPagerAdapter
konstruktor.sumber
Saya mengesampingkan metode Hitung dari FragmentStatePagerAdapter yang terkait dan mengembalikannya jumlah total dikurangi jumlah halaman yang disembunyikan:
Jadi, jika ada 3 fragmen yang pada awalnya ditambahkan ke ViewPager, dan hanya 2 fragmen pertama yang akan ditampilkan sampai beberapa kondisi terpenuhi, ganti jumlah halaman dengan mengatur TrimmedPages ke 1 dan seharusnya hanya menampilkan dua halaman pertama.
Ini berfungsi baik untuk halaman di bagian akhir, tetapi tidak akan sangat membantu untuk yang di awal atau di tengah (meskipun ada banyak cara untuk melakukan ini).
sumber