J'ai une Text
avec un long texte à l'intérieur d'une ScrollView
et je veux détecter le moment où l'utilisateur a fait défiler l'écran à la fin du texte pour pouvoir activer un bouton.
J'ai débogué l'objet événement à partir de l'événement onScroll
mais il ne semble pas que je puisse utiliser une valeur.
Je l'ai fait comme ça:
import React from 'react';
import {ScrollView, Text} from 'react-native';
const isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
const paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >=
contentSize.height - paddingToBottom;
};
const MyCoolScrollViewComponent = ({enableSomeButton}) => (
<ScrollView
onScroll={({nativeEvent}) => {
if (isCloseToBottom(nativeEvent)) {
enableSomeButton();
}
}}
scrollEventThrottle={400}
>
<Text>Here is very long lorem ipsum or something...</Text>
</ScrollView>
);
export default MyCoolScrollViewComponent;
Je voulais ajouter paddingToBottom
car il n'est généralement pas nécessaire que ScrollView défile jusqu'au dernier pixel. Mais si vous voulez que cela règle paddingToBottom à zéro.
<... onScroll={(e) => {
let paddingToBottom = 10;
paddingToBottom += e.nativeEvent.layoutMeasurement.height;
if(e.nativeEvent.contentOffset.y >= e.nativeEvent.contentSize.height - paddingToBottom) {
// make something...
}
}}>...
comme ceci réagissent natif 0,44
Une autre solution pourrait être d’utiliser une variable ListView
avec une seule ligne (votre texte) associée à la méthode onEndReached
. Voir la documentation ici
Pour ScrollView horizontal (par exemple, carrousels), remplacez la fonction isCloseToBottom
par isCloseToRight
isCloseToRight = ({ layoutMeasurement, contentOffset, contentSize }) => {
const paddingToRight = 20;
return layoutMeasurement.width + contentOffset.x >= contentSize.width - paddingToRight;
};
En complément de la réponse de Henrik R:
Si vous devez savoir si l'utilisateur a atteint la fin du contenu au moment du montage (si le contenu peut être trop long, en fonction de la taille du périphérique), voici ma solution:
<ScrollView
onLayout={this.onLayoutScrollView}
onScroll={this.onScroll}>
<View onLayout={this.onLayoutScrollContent}>
{/*...*/}
</View>
</ScrollView>
en combinaison avec
onLayout(wrapper, { nativeEvent }) {
if (wrapper) {
this.setState({
wrapperHeight: nativeEvent.layout.height,
});
} else {
this.setState({
contentHeight: nativeEvent.layout.height,
isCloseToBottom:
this.state.wrapperHeight - nativeEvent.layout.height >= 0,
});
}
}
@Henrik R a raison . Mais vous devriez aussi utiliser Math.ceil ().
function handleInfinityScroll(event) {
let mHeight = event.nativeEvent.layoutMeasurement.height;
let cSize = event.nativeEvent.contentSize.height;
let Y = event.nativeEvent.contentOffset.y;
if(Math.ceil(mHeight + Y) >= cSize) return true;
return false;
}
Au fur et à mesure que les gens m'aident, j'ajouterai le code simple qu'ils ont écrit pour atteindre les événements haut et bas et j'ai fait une petite illustration pour simplifier les choses
<ScrollView
onScroll={({nativeEvent})=>{
if(isCloseToTop(nativeEvent)){
//do something
}
if(isCloseToBottom(nativeEvent)){
//do something
}
}}
>
...contents
</ScrollView>
isCloseToBottom({layoutMeasurement, contentOffset, contentSize}){
return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;
}
ifCloseToTop({layoutMeasurement, contentOffset, contentSize}){
return contentOffset.y == 0;
}