检测到 ScrollView 已经结束

Detect ScrollView has reached the end

我有一个 Text,在 ScrollView 中有长文本,我想检测用户何时滚动到文本的末尾,以便我可以启用一个按钮。

我一直在调试来自 onScroll 事件的事件对象,但似乎没有任何我可以使用的值。

我是这样做的:

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;

我想添加 paddingToBottom 因为通常不需要将 ScrollView 滚动到底部直到最后一个像素。但是,如果您希望将 paddingToBottom 设置为零。

另一种解决方案是使用 ListView 和具有 onEndReached 方法的单行(您的文本)。请参阅文档 here

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

喜欢这个 react-native 0.44

对于水平滚动视图(例如轮播),将 isCloseToBottom 函数替换为 isCloseToRight

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

作为对 Henrik R 回答的补充:

如果您需要知道用户是否已在加载时到达内容的末尾(内容是否可能太长,具体取决于设备大小)- 这是我的解决方案:

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

结合

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

由于人们在这里提供帮助,我将添加他们编写的简单代码以实现到达顶部和到达底部事件,并且我做了一些插图以使事情变得更简单

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

@Henrik R 说得对。 但是你也应该使用 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;
}

我使用 ScrollView,这对我有用

这是我的解决方案:

我将 onMomentumScrollEnd 属性传递给了 scrollView,并在此基础上 event.nativeEvent 我在 ScrollView 中实现了 onEndReached 功能

 onMomentumScrollEnd={(event) => { 
          if (isCloseToBottom(event.nativeEvent)) {
            LoadMoreRandomData()
          }
         }
       }}

  const isCloseToBottom = ({layoutMeasurement, contentOffset, contentSize}) => {
const paddingToBottom = 20;
return layoutMeasurement.height + contentOffset.y >=
  contentSize.height - paddingToBottom;

};

const isCloseToBottom = async ({ layoutMeasurement, contentOffset, contentSize }) => {
const paddingToBottom = 120
return layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom}


 <ScrollView
    onMomentumScrollEnd={({ nativeEvent }) => {
      if (isCloseToBottom(nativeEvent)) {
        loadMoreData()
      }
    }}
    scrollEventThrottle={1}
  >

上面的答案是正确的,但是在滚动视图中到达终点时的回调使用onMomentumScrollEnd而不是onScroll