Detect ScrollView has reached the end

拟墨画扇 提交于 2019-11-30 04:34:32

I did it like this:

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;

I wanted to add paddingToBottom because usually it is not needed that ScrollView is scrolled to the bottom till last pixel. But if you want that set paddingToBottom to zero.

<... onScroll={(e) => {
        let paddingToBottom = 10;
        paddingToBottom += e.nativeEvent.layoutMeasurement.height;
        if(e.nativeEvent.contentOffset.y >= e.nativeEvent.contentSize.height - paddingToBottom) {
          // make something...
        }
      }}>...

like this react-native 0.44

As people helped here I will add the simple code they write to make reached to top and reached to bottom event and I did a little illustration to make things simpler

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

Another solution could be to use a ListView with a single row (your text) which has onEndReached method. See the documentation here

For Horizontal ScrollView (e.g. Carousels) replace isCloseToBottom function with isCloseToRight

isCloseToRight = ({ layoutMeasurement, contentOffset, contentSize }) => {
    const paddingToRight = 20;
    return layoutMeasurement.width + contentOffset.x >= contentSize.width - paddingToRight;
};
Fuad Cavadov

@Henrik R's right. But you should use Math.ceil() too.

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

As an addition to the answer of Henrik R:

If you need to know wether the user has reached the end of the content at mount time (if the content may or may not be too long, depending on device size) - here is my solution:

<ScrollView 
        onLayout={this.onLayoutScrollView}
        onScroll={this.onScroll}>
    <View onLayout={this.onLayoutScrollContent}>
        {/*...*/}
    </View>
</ScrollView>

in combination with

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,
        });
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!