Apakah mungkin untuk mendapatkan posisi scroll saat ini, atau halaman saat ini dari <ScrollView>
komponen di React Native?
Jadi sesuatu seperti:
<ScrollView
horizontal={true}
pagingEnabled={true}
onScrollAnimationEnd={() => {
// get this scrollview's current page or x/y scroll position
}}>
this.state.data.map(function(e, i) {
<ImageCt key={i}></ImageCt>
})
</ScrollView>
ios
reactjs
react-native
Sang
sumber
sumber
Jawaban:
Mencoba.
Lalu:
sumber
event.nativeEvent.contentOffset.x
jika Anda memiliki ScrollView horizontal;) Terima kasih!scrollEventThrottle
ke 16 atau lebih rendah (untuk mendapatkan acara untuk setiap bingkai), tidak ada jaminan bahwa ini akan melaporkan offset pada bingkai terakhir - artinya untuk memastikan bahwa Anda memiliki offset yang tepat setelah pengguliran selesai, Anda perlu mengaturscrollEventThrottle={16}
dan menerima dampak kinerja itu.event.nativeEvent.contentOffset.y
?Penafian: yang berikut ini terutama merupakan hasil eksperimen saya sendiri di React Native 0.50. The
ScrollView
dokumentasi saat ini hilang banyak informasi yang tercakup di bawah ini; misalnyaonScrollEndDrag
sama sekali tidak terdokumentasi. Karena semua yang ada di sini bergantung pada perilaku yang tidak terdokumentasi, sayangnya saya tidak dapat berjanji bahwa informasi ini akan tetap benar setahun atau bahkan sebulan dari sekarang.Juga, segala sesuatu di bawah ini mengasumsikan tampilan gulir vertikal murni yang offset y nya kita minati; menterjemahkan ke x offset, bila diperlukan semoga menjadi latihan yang mudah bagi pembaca.
Berbagai penangan acara sedang
ScrollView
mengambilevent
dan membiarkan Anda mendapatkan posisi gulir saat ini melaluievent.nativeEvent.contentOffset.y
. Beberapa penangan ini memiliki perilaku yang sedikit berbeda antara Android dan iOS, seperti yang dijelaskan di bawah ini.onScroll
Di Android
Menyalakan setiap bingkai saat pengguna menggulir, pada setiap bingkai saat tampilan gulir meluncur setelah pengguna melepaskannya, pada bingkai terakhir saat tampilan gulir berhenti, dan juga setiap kali offset tampilan gulir berubah sebagai akibat dari bingkainya berubah (misalnya karena rotasi dari lanskap ke potret).
Di iOS
Kebakaran saat pengguna menyeret atau saat tampilan gulir meluncur, pada frekuensi tertentu yang ditentukan oleh
scrollEventThrottle
dan paling banyak sekali per frame saatscrollEventThrottle={16}
. Jika pengguna melepaskan tampilan gulir saat memiliki cukup momentum untuk meluncur,onScroll
penangan juga akan aktif saat berhenti setelah meluncur. Namun, jika pengguna menyeret dan kemudian melepaskan pandangan gulir sementara itu stasioner,onScroll
yang tidak dijamin api untuk posisi akhir kecualiscrollEventThrottle
telah diatur sedemikian rupa sehinggaonScroll
kebakaran setiap frame bergulir.Ada biaya kinerja untuk pengaturan
scrollEventThrottle={16}
yang dapat dikurangi dengan mengaturnya ke angka yang lebih besar. Namun, ini berartionScroll
tidak akan mengaktifkan setiap frame.onMomentumScrollEnd
Kebakaran saat tampilan gulir berhenti setelah meluncur. Tidak menyala sama sekali jika pengguna melepaskan tampilan gulir saat tidak bergerak sehingga tidak meluncur.
onScrollEndDrag
Kebakaran saat pengguna berhenti menyeret tampilan gulir - terlepas dari apakah tampilan gulir tidak bergerak atau mulai meluncur.
Mengingat perbedaan perilaku ini, cara terbaik untuk melacak penggantian kerugian bergantung pada keadaan Anda yang sebenarnya. Dalam kasus yang paling rumit (Anda perlu mendukung Android dan iOS, termasuk menangani perubahan dalam
ScrollView
bingkai karena rotasi, dan Anda tidak ingin menerima penalti kinerja pada Android dari pengaturanscrollEventThrottle
ke 16), dan Anda perlu menangani mengubah konten dalam tampilan gulir juga, maka itu benar-benar berantakan.Kasus paling sederhana adalah jika Anda hanya perlu menangani Android; gunakan saja
onScroll
:Untuk lebih mendukung iOS, jika Anda senang untuk mengaktifkan
onScroll
handler setiap frame dan menerima implikasi kinerja dari itu, dan jika Anda tidak perlu menangani perubahan frame, maka ini hanya sedikit lebih rumit:Untuk mengurangi overhead kinerja di iOS sambil tetap menjamin bahwa kami merekam posisi apa pun yang ditetapkan oleh tampilan gulir, kami dapat meningkatkan
scrollEventThrottle
dan juga menyediakanonScrollEndDrag
penangan:Tetapi jika kita ingin menangani perubahan bingkai (misalnya karena kita mengizinkan perangkat untuk diputar, mengubah ketinggian yang tersedia untuk bingkai tampilan gulir) dan / atau perubahan konten, maka kita harus menerapkan keduanya
onContentSizeChange
danonLayout
untuk melacak ketinggian keduanya. bingkai tampilan gulir dan kontennya, dan dengan demikian terus menghitung offset maksimum yang mungkin dan menyimpulkan saat offset secara otomatis berkurang karena bingkai atau ukuran konten berubah:Ya, itu sangat mengerikan. Saya juga tidak 100% yakin bahwa ini akan selalu berfungsi dengan benar jika Anda secara bersamaan mengubah ukuran bingkai dan konten tampilan gulir. Tapi itu yang terbaik yang bisa saya hasilkan, dan sampai fitur ini ditambahkan dalam kerangka itu sendiri , saya pikir ini adalah yang terbaik yang bisa dilakukan siapa pun.
sumber
Jawaban Brad Oyler benar. Tetapi Anda hanya akan menerima satu acara. Jika Anda perlu mendapatkan pembaruan konstan dari posisi gulir, Anda harus mengatur
scrollEventThrottle
prop, seperti ini:Dan event handler:
Ketahuilah bahwa Anda mungkin mengalami masalah kinerja. Sesuaikan throttle dengan benar. 16 memberi Anda pembaruan paling banyak. 0 hanya satu.
sumber
function(event) { }
.scrollEventThrottle={16}
tidak tidak memberikan "kurang" update; nomor apa pun dalam kisaran 1-16 memberi Anda tingkat pembaruan semaksimal mungkin. Default 0 memberi Anda (di iOS) satu peristiwa ketika pengguna mulai menggulir dan kemudian tidak ada pembaruan berikutnya (yang sangat tidak berguna dan mungkin bug); defaultnya bukan "sekali per frame". Selain dua kesalahan dalam komentar Anda, pernyataan Anda yang lain tidak bertentangan dengan apa pun yang dikatakan jawabannya (meskipun Anda sepertinya berpikir demikian).Jika Anda hanya ingin mendapatkan posisi saat ini (misalnya ketika beberapa tombol ditekan) daripada melacaknya setiap kali pengguna menggulir, maka memanggil
onScroll
pendengar akan menyebabkan masalah kinerja. Saat ini, cara paling berkinerja untuk mendapatkan posisi scroll saat ini menggunakan react-native-invoke . Ada contoh untuk hal ini, tetapi paket melakukan banyak hal lainnya.Bacalah di sini. https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd
sumber
Untuk mendapatkan x / y setelah gulir berakhir seperti yang diminta oleh pertanyaan asli, cara termudah mungkin adalah ini:
sumber
onMomentumScrollEnd
hanya dipicu jika tampilan gulir memiliki beberapa momentum saat pengguna melepaskannya. Jika mereka melepaskan saat tampilan gulir tidak bergerak, Anda tidak akan pernah mendapatkan peristiwa momentum apa pun.Jawaban di atas menjelaskan bagaimana mendapatkan posisi menggunakan API yang berbeda
onScroll
,onMomentumScrollEnd
dll; Jika Anda ingin mengetahui indeks halaman, Anda dapat menghitungnya menggunakan nilai offset.Di iOS, hubungan antara ScrollView dan wilayah yang terlihat adalah sebagai berikut:
ref: https://www.objc.io/issues/3-views/scroll-view/
sumber
Ini adalah bagaimana akhirnya mendapatkan posisi gulir saat ini langsung dari tampilan. Yang saya lakukan hanyalah menggunakan pendengar acara gulir dan scrollEventThrottle. Saya kemudian meneruskannya sebagai acara untuk menangani fungsi gulir yang saya buat dan memperbarui alat peraga saya.
sumber
penggunaan onScroll memasuki putaran tak terbatas. onMomentumScrollEnd atau onScrollEndDrag dapat digunakan sebagai gantinya
sumber
Adapun halaman, saya sedang mengerjakan komponen tingkat tinggi yang pada dasarnya menggunakan metode di atas untuk melakukan hal ini. Ini sebenarnya hanya membutuhkan sedikit waktu ketika Anda sampai ke seluk-beluk seperti tata letak awal dan perubahan konten. Saya tidak akan mengklaim telah melakukannya dengan 'benar', tetapi dalam arti tertentu saya akan mempertimbangkan jawaban yang benar untuk menggunakan komponen yang melakukan ini dengan hati-hati dan konsisten.
Lihat: react-native-paged-scroll-view . Akan menyukai umpan balik, bahkan jika saya telah melakukan semuanya dengan salah!
sumber
Saya yakin
contentOffset
akan memberi Anda objek yang berisi scroll offset kiri atas:http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
sumber