web-dev-qa-db-fra.com

Detect ScrollView a atteint la fin

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.

18
Eldelshell

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.

49
Henrik R
<... 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

10

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

4
David

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;
};
2
deadcoder0904

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,
        });
    }
}
1
Malte Peters

@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;
}

enter image description here

0
Fuad Cavadov

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

 Layout and vars values

<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;
}
0
Louay Alosh