在 React Native ScrollView 中检测滚动结束,捕捉到页面

Detect scroll end in React Native ScrollView, snap to page

React Native ScrollView has a prop pagingEnabled 。但是,它假定ScrollView中每个页面(或子组件)的宽度等于ScrollView的宽度。

我们如何解决这个问题才能使其在小于 ScrollView 的页面上正常工作?

是否可以检测到用户何时停止滚动?然后我们可以轻松编写自己的代码来捕捉到正确的页面。

编辑:还有一些其他方法可以通过使用仅在 iOS 上可用的道具来修复此问题,因此这在 Android 上尤其是一个问题。

您可以为 React Native ScrollView 设置两个不同的道具,它们需要一个回调来通知滚动已经结束。 (它们现在都已记录在案。)


onScrollEndDrag function

一旦用户松开 ScrollView(将手指从屏幕上移开)就调用。

工作示例:https://rnplay.org/apps/Ufv6Cg(不再可用)


onMomentumScrollEnd function

当ScrollView停止滑动时调用(通常会在用户手指离开屏幕后继续滑动一点点)。

工作示例:https://rnplay.org/apps/BPgG_g(不再可用)


注意: 我无法在 API 文档中找到任何 React Native 组件的方法,但它们的工作方式如示例所示。我看到他们用 here in react-native-snap-carousel.

作为一个选项,您可以使用 debounce package。 别忘了 clear() 它。

import { debounce } from 'debounce';

...

const listenerDebounce = debounce((_) => {
    // Scroll Did End
  }, 160);

return <FlatList
  {...yourProps}
  onScroll={Animated.event(
    [{
        nativeEvent: {
            contentOffset: { y: scrollOffsetValue }
        }
    }],
    {
        useNativeDriver: true,
        listener: listenerDebounce
    },
)
/>;

...

另一种选择是使用 snapToOffsets 属性,它完全符合您的要求。

This can be used for paginating through variously sized children that have lengths smaller than the scroll view.

我是这样做的:

import React from 'react';
import {ScrollView} from 'react-native';
    
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;
}
    
const HomeScreen= ({navigation}) => (
  <ScrollView
    onScroll={({event}) => {
      if (handleInfinityScroll(event)) {
        console.log("END");
      }
    }}
  >
    <></>
  </ScrollView>
);
    
export default HomeScreen;