Ist es möglich, die aktuelle Bildlaufposition oder die aktuelle Seite einer <ScrollView>
Komponente in React Native abzurufen?
Also so etwas wie:
<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
quelle
quelle
Antworten:
Versuchen.
Und dann:
quelle
event.nativeEvent.contentOffset.x
wenn du eine horizontale ScrollView hast;) Danke!scrollEventThrottle
es keine Garantie dafür gibt, dass der Versatz im letzten Bild angezeigt wird, es sei denn, Sie stellen 16 oder weniger ein (um ein Ereignis für jedes einzelne Bild zu erhalten). Dies bedeutet, dass Sie nach Abschluss des Bildlaufs den richtigen Versatz haben. Sie müssenscrollEventThrottle={16}
die Auswirkungen auf die Leistung festlegen und akzeptieren.event.nativeEvent.contentOffset.y
?Haftungsausschluss: Was folgt, ist in erster Linie das Ergebnis meiner eigenen Experimente in React Native 0.50. In der
ScrollView
Dokumentation fehlen derzeit viele der unten behandelten Informationen. zum BeispielonScrollEndDrag
ist völlig undokumentiert. Da hier alles auf undokumentiertem Verhalten beruht, kann ich leider nicht versprechen, dass diese Informationen in einem Jahr oder sogar einem Monat korrekt bleiben.Außerdem setzt alles unten eine rein vertikale Bildlaufansicht voraus, deren y- Versatz uns interessiert; Das Übersetzen in x Offsets, falls erforderlich, ist hoffentlich eine einfache Übung für den Leser.
Verschiedene Event-Handler
ScrollView
nehmen eine Aufnahmeevent
und lassen Sie die aktuelle Bildlaufposition über abrufenevent.nativeEvent.contentOffset.y
. Einige dieser Handler haben ein etwas anderes Verhalten zwischen Android und iOS, wie unten beschrieben.onScroll
Auf Android
Löst jedes Bild aus, während der Benutzer einen Bildlauf durchführt, auf jedem Bild, während die Bildlaufansicht nach dem Loslassen durch den Benutzer gleitet, auf dem letzten Bild, wenn die Bildlaufansicht zum Stillstand kommt, und auch dann, wenn sich der Versatz der Bildlaufansicht aufgrund des Bilds ändert Ändern (z. B. durch Drehung von Querformat zu Hochformat).
Unter iOS
Wird ausgelöst, während der Benutzer zieht oder während die Bildlaufansicht gleitet, mit einer Häufigkeit, die von
scrollEventThrottle
und höchstens einmal pro Bild bestimmt wird, wennscrollEventThrottle={16}
. Wenn der Benutzer die Bildlaufansicht freigibt, während er genügend Schwung zum Gleiten hat, wird deronScroll
Handler auch ausgelöst, wenn er nach dem Gleiten zur Ruhe kommt. Wenn der Benutzer die Bildlaufansicht jedoch zieht und dann im Stillstand freigibt,onScroll
ist dies nicht der Fall garantiert, dass sie für die endgültige Position ausgelöstscrollEventThrottle
wird, es sei denn, sie wurde so eingestellt, dassonScroll
jedes Bildlaufbild ausgelöst wird.Das Einstellen verursacht Leistungskosten, die
scrollEventThrottle={16}
durch Einstellen auf eine größere Anzahl reduziert werden können. Dies bedeutet jedoch, dassonScroll
nicht jeder Frame ausgelöst wird.onMomentumScrollEnd
Wird ausgelöst, wenn die Bildlaufansicht nach dem Gleiten zum Stillstand kommt. Wird überhaupt nicht ausgelöst, wenn der Benutzer die Bildlaufansicht im Stillstand so freigibt, dass sie nicht gleitet.
onScrollEndDrag
Wird ausgelöst, wenn der Benutzer das Ziehen der Bildlaufansicht beendet - unabhängig davon, ob die Bildlaufansicht stationär bleibt oder zu gleiten beginnt.
Angesichts dieser Verhaltensunterschiede hängt der beste Weg, den Versatz zu verfolgen, von Ihren genauen Umständen ab. Im kompliziertesten Fall (Sie müssen Android und iOS unterstützen, einschließlich der Behandlung von Änderungen im
ScrollView
Rahmen aufgrund von Rotation, und Sie möchten die Leistungseinbußen bei Android von EinstellungscrollEventThrottle
auf 16 nicht akzeptieren ), und Sie müssen damit umgehen ändert sich auch der Inhalt in der Bildlaufansicht, dann ist es ein verdammtes Durcheinander.Der einfachste Fall ist, wenn Sie nur mit Android umgehen müssen. benutze einfach
onScroll
:Um iOS zusätzlich zu unterstützen , ist es nur ein bisschen komplizierter , wenn Sie den
onScroll
Handler gerne in jedem Frame auslösen und die Auswirkungen auf die Leistung akzeptieren und wenn Sie keine Frame-Änderungen vornehmen müssen:Um den Leistungsaufwand unter iOS zu verringern und gleichzeitig sicherzustellen, dass alle Positionen aufgezeichnet werden, an denen sich die Bildlaufansicht befindet, können wir
scrollEventThrottle
denonScrollEndDrag
Handler erhöhen und zusätzlich bereitstellen :Wenn wir jedoch Rahmenänderungen (z. B. weil wir das Gerät drehen lassen, die verfügbare Höhe für den Rahmen der Bildlaufansicht ändern) und / oder Inhaltsänderungen verarbeiten möchten, müssen wir beide zusätzlich implementieren
onContentSizeChange
undonLayout
die Höhe beider verfolgen den Rahmen und den Inhalt der Bildlaufansicht und berechnen dabei kontinuierlich das Maximum möglichen Versatz und schließen daraus, wenn der Versatz aufgrund einer Änderung der Rahmen- oder Inhaltsgröße automatisch verringert wurde:Ja, es ist ziemlich schrecklich. Ich bin mir auch nicht 100% sicher, dass es immer richtig funktioniert, wenn Sie gleichzeitig die Größe des Rahmens und den Inhalt der Bildlaufansicht ändern. Aber es ist das Beste, was ich mir vorstellen kann, und bis diese Funktion innerhalb des Frameworks selbst hinzugefügt wird , denke ich, dass dies das Beste ist, was jeder tun kann.
quelle
Brad Oylers Antwort ist richtig. Sie erhalten jedoch nur eine Veranstaltung. Wenn Sie die Bildlaufposition ständig aktualisieren müssen, sollten Sie die
scrollEventThrottle
Requisite wie folgt einstellen :Und der Event-Handler:
Beachten Sie, dass möglicherweise Leistungsprobleme auftreten. Stellen Sie den Gashebel entsprechend ein. 16 gibt Ihnen die meisten Updates. 0 nur eine.
quelle
function(event) { }
.scrollEventThrottle={16}
ist nicht geben Sie „weniger“ Updates; Jede Zahl im Bereich von 1 bis 16 gibt Ihnen die maximal mögliche Aktualisierungsrate. Der Standardwert 0 gibt Ihnen (unter iOS) ein Ereignis, wenn der Benutzer mit dem Scrollen beginnt, und dann keine nachfolgenden Updates (was ziemlich nutzlos und möglicherweise ein Fehler ist). Der Standardwert ist nicht "einmal pro Frame". Abgesehen von diesen beiden Fehlern in Ihrem Kommentar widersprechen Ihre anderen Behauptungen nichts, was in der Antwort steht (obwohl Sie zu glauben scheinen, dass dies der Fall ist).Wenn Sie einfach die aktuelle Position abrufen möchten (z. B. wenn eine Taste gedrückt wird), anstatt sie zu verfolgen, wenn der Benutzer einen Bildlauf durchführt, führt das Aufrufen eines
onScroll
Listeners zu Leistungsproblemen. Derzeit ist die reaktionsschnellste Methode, um einfach die aktuelle Bildlaufposition abzurufen, die Verwendung von react-native-invoke Pakets . Es gibt ein Beispiel für genau diese Sache, aber das Paket macht mehrere andere Dinge.Lesen Sie hier darüber. https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd
quelle
Der einfachste Weg, um das x / y nach dem Ende des Bildlaufs zu erhalten, als die ursprünglichen Fragen angefordert wurden, ist wahrscheinlich der folgende:
quelle
onMomentumScrollEnd
wird nur ausgelöst, wenn die Bildlaufansicht einen gewissen Schwung hat, wenn der Benutzer sie loslässt. Wenn sie freigegeben werden, während sich die Bildlaufansicht nicht bewegt, erhalten Sie nie eines der Momentum-Ereignisse.Die oben genannten Antworten sagen , wie die Position zu bekommen verschiedene API,
onScroll
,onMomentumScrollEnd
etc; Wenn Sie den Seitenindex kennen möchten, können Sie ihn anhand des Versatzwerts berechnen.In iOS ist die Beziehung zwischen ScrollView und dem sichtbaren Bereich wie folgt:
Ref: https://www.objc.io/issues/3-views/scroll-view/
quelle
Auf diese Weise wurde die aktuelle Bildlaufposition live aus der Ansicht angezeigt. Ich verwende lediglich den On-Scroll-Ereignis-Listener und das scrollEventThrottle. Ich übergebe es dann als Ereignis, um die von mir erstellte Bildlauffunktion zu handhaben und meine Requisiten zu aktualisieren.
quelle
Die Verwendung von onScroll tritt in eine Endlosschleife ein. Stattdessen können onMomentumScrollEnd oder onScrollEndDrag verwendet werden
quelle
Was die Seite betrifft, arbeite ich an einer Komponente höherer Ordnung, die im Grunde die oben genannten Methoden verwendet, um genau dies zu tun. Tatsächlich dauert es nur ein wenig, bis Sie sich mit den Feinheiten wie dem anfänglichen Layout und den Änderungen des Inhalts befassen. Ich werde nicht behaupten, es "richtig" gemacht zu haben, aber in gewissem Sinne würde ich die richtige Antwort in Betracht ziehen, um eine Komponente zu verwenden, die dies sorgfältig und konsequent tut.
Siehe: React-Native-Paged-Scroll-Ansicht . Würde mich über Feedback freuen, auch wenn ich alles falsch gemacht habe!
quelle
Ich glaube
contentOffset
, Sie erhalten ein Objekt mit dem Bildlaufversatz oben links:http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
quelle