Est-il possible d'obtenir la position de défilement actuelle ou la page actuelle d'un <ScrollView>
composant dans React Native?
Donc quelque chose comme:
<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
A chanté
la source
la source
Réponses:
Essayer.
Puis:
la source
event.nativeEvent.contentOffset.x
si vous avez un ScrollView horizontal;) Merci!scrollEventThrottle
sur 16 ou moins (pour obtenir un événement pour chaque image), il n'y a aucune garantie que cela signalera le décalage sur l' image finale - ce qui signifie que pour être sûr que vous avez le bon décalage une fois le défilement terminé, vous devez définirscrollEventThrottle={16}
et accepter l'impact sur les performances de cela.event.nativeEvent.contentOffset.y
?Avertissement: ce qui suit est principalement le résultat de ma propre expérimentation dans React Native 0.50. La
ScrollView
documentation est actuellement manque beaucoup des informations couvertes ci - dessous; par exempleonScrollEndDrag
est complètement non documenté. Puisque tout ici repose sur un comportement non documenté, je ne peux malheureusement pas promettre que ces informations resteront correctes dans un an ou même un mois.De plus, tout ce qui suit suppose une vue de défilement purement verticale dont le décalage y nous intéresse; la conversion en décalages x , si nécessaire, est, espérons-le, un exercice facile pour le lecteur.
Divers gestionnaires d'événements sur une
ScrollView
priseevent
et vous permettent d'obtenir la position de défilement actuelle viaevent.nativeEvent.contentOffset.y
. Certains de ces gestionnaires ont un comportement légèrement différent entre Android et iOS, comme détaillé ci-dessous.onScroll
Sur Android
Déclenche chaque image pendant que l'utilisateur fait défiler, sur chaque image pendant que la vue de défilement glisse après que l'utilisateur la libère, sur l'image finale lorsque la vue de défilement s'arrête, et également chaque fois que le décalage de la vue de défilement change en raison de son cadre changeant (par exemple en raison de la rotation du paysage au portrait).
Sur iOS
Se déclenche lorsque l'utilisateur fait glisser ou lorsque la vue de défilement glisse, à une fréquence déterminée par
scrollEventThrottle
et au plus une fois par image quandscrollEventThrottle={16}
. Si l'utilisateur libère la vue de défilement alors qu'il a suffisamment d'élan pour glisser, leonScroll
gestionnaire se déclenchera également lorsqu'il s'arrêtera après avoir glissé. Cependant, si l'utilisateur fait glisser puis relâche la vue de défilement alors qu'elle est stationnaire, ilonScroll
n'est pas garanti de se déclencher pour la position finale à moins qu'ilscrollEventThrottle
n'ait été défini de manière àonScroll
déclencher chaque image de défilement.Il y a un coût de performance au réglage
scrollEventThrottle={16}
qui peut être réduit en le définissant sur un nombre plus grand. Cependant, cela signifie queonScroll
ne déclenchera pas toutes les images.onMomentumScrollEnd
Se déclenche lorsque la vue de défilement s'arrête après un vol plané. Ne se déclenche pas du tout si l'utilisateur libère la vue de défilement alors qu'elle est stationnaire de sorte qu'elle ne glisse pas.
onScrollEndDrag
Se déclenche lorsque l'utilisateur arrête de faire glisser la vue de défilement, que la vue de défilement soit laissée stationnaire ou qu'elle commence à glisser.
Compte tenu de ces différences de comportement, la meilleure façon de suivre le décalage dépend de vos circonstances précises. Dans le cas le plus compliqué (vous devez prendre en charge Android et iOS, y compris la gestion des changements dans le
ScrollView
cadre de s en raison de la rotation, et vous ne voulez pas accepter la pénalité de performances sur Android du paramètrescrollEventThrottle
à 16), et vous devez gérer modifications du contenu dans la vue de défilement aussi, alors c'est un sacré désordre.Le cas le plus simple est si vous avez seulement besoin de gérer Android; utilisez simplement
onScroll
:Pour prendre en charge également iOS, si vous êtes heureux de déclencher le
onScroll
gestionnaire à chaque image et d'en accepter les implications sur les performances, et si vous n'avez pas besoin de gérer les changements de cadre, alors ce n'est qu'un peu plus compliqué:Pour réduire la surcharge de performances sur iOS tout en garantissant que nous enregistrons toute position sur laquelle la vue de défilement s'installe, nous pouvons augmenter
scrollEventThrottle
et fournir en plus unonScrollEndDrag
gestionnaire:Mais si nous voulons gérer les changements de cadre (par exemple, parce que nous autorisons la rotation de l'appareil, en changeant la hauteur disponible pour le cadre de la vue de défilement) et / ou les changements de contenu, nous devons également implémenter les deux
onContentSizeChange
etonLayout
garder une trace de la hauteur des deux le cadre de la vue de défilement et son contenu, et ainsi calculer en permanence le décalage maximum possible et déduire quand le décalage a été automatiquement réduit en raison d'un changement de taille de cadre ou de contenu:Ouais, c'est assez horrible. Je ne suis pas non plus certain à 100% que cela fonctionnera toujours correctement dans les cas où vous modifiez simultanément la taille du cadre et le contenu de la vue de défilement. Mais c'est le mieux que je puisse proposer, et jusqu'à ce que cette fonctionnalité soit ajoutée dans le cadre lui - même , je pense que c'est le mieux que quiconque puisse faire.
la source
La réponse de Brad Oyler est correcte. Mais vous ne recevrez qu'un seul événement. Si vous avez besoin d'obtenir des mises à jour constantes de la position de défilement, vous devez définir le
scrollEventThrottle
prop, comme ceci:Et le gestionnaire d'événements:
Sachez que vous pouvez rencontrer des problèmes de performances. Réglez l'accélérateur en conséquence. 16 vous donne le plus de mises à jour. 0 un seul.
la source
function(event) { }
.scrollEventThrottle={16}
ne pas vous donner des mises à jour « moins »; tout nombre compris entre 1 et 16 vous donne le taux maximum de mises à jour possible. La valeur par défaut de 0 vous donne (sur iOS) un événement lorsque l'utilisateur commence à faire défiler, puis aucune mise à jour ultérieure (ce qui est assez inutile et peut-être un bogue); la valeur par défaut n'est pas "une fois par image". Outre ces deux erreurs dans votre commentaire, vos autres affirmations ne contredisent rien de ce que dit la réponse (même si vous semblez penser qu'elles le font).Si vous souhaitez simplement obtenir la position actuelle (par exemple, lorsque vous appuyez sur un bouton) plutôt que de la suivre chaque fois que l'utilisateur fait défiler, alors appeler un
onScroll
auditeur va causer des problèmes de performances. Actuellement, le moyen le plus efficace d'obtenir simplement la position de défilement actuelle consiste à utiliser le package react-native-invoke . Il existe un exemple pour cette chose exacte, mais le package fait plusieurs autres choses.Lisez à ce sujet ici. https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd
la source
Pour obtenir le x / y après la fin du défilement comme le demandaient les questions d'origine, le moyen le plus simple est probablement le suivant:
la source
onMomentumScrollEnd
n'est déclenchée que si la vue de défilement a un certain élan lorsque l'utilisateur la lâche. S'ils se relâchent alors que la vue de défilement ne bouge pas, vous n'obtiendrez jamais aucun des événements d'élan.Les réponses ci-dessus indiquent comment obtenir la position en utilisant différentes API
onScroll
,onMomentumScrollEnd
etc. Si vous souhaitez connaître l'index de la page, vous pouvez le calculer à l'aide de la valeur de décalage.Dans iOS, la relation entre ScrollView et la région visible est la suivante:
réf: https://www.objc.io/issues/3-views/scroll-view/
la source
C'est ainsi que nous avons obtenu la position de défilement actuelle en direct à partir de la vue. Tout ce que je fais, c'est utiliser l'écouteur d'événement on scroll et scrollEventThrottle. Je le passe ensuite comme un événement pour gérer la fonction de défilement que j'ai créée et mettre à jour mes accessoires.
la source
l'utilisation de onScroll entre en boucle infinie. onMomentumScrollEnd ou onScrollEndDrag peuvent être utilisés à la place
la source
En ce qui concerne la page, je travaille sur un composant d'ordre supérieur qui utilise essentiellement les méthodes ci-dessus pour faire exactement cela. En fait, cela prend juste un peu de temps lorsque vous abordez les subtilités telles que la mise en page initiale et les changements de contenu. Je ne prétendrai pas l'avoir fait «correctement», mais dans un certain sens, je considérerais la bonne réponse pour utiliser un composant qui le fait avec soin et cohérence.
Voir: react-native-paged-scroll-view . J'adorerais les commentaires, même si c'est que j'ai tout mal fait!
la source
Je crois
contentOffset
que vous donnera un objet contenant le décalage de défilement en haut à gauche:http://facebook.github.io/react-native/docs/scrollview.html#contentoffset
la source