Определить ScrollView достиг конца

У меня есть Text с длинным текстом внутри ScrollView и я хочу определить, когда пользователь прокрутил текст до конца, чтобы я мог включить кнопку.

Я отлаживал объект события из onScroll событие, но не кажется, что я могу использовать какую-либо ценность.

11 ответов

Решение

Я сделал это так:

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 было равно нулю.

Поскольку люди помогли здесь, я добавлю простой код, который они пишут, чтобы событие достигло верха и низа, и я сделал небольшую иллюстрацию, чтобы сделать вещи проще

Значения Layout и Vars

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

как это реагировать родной 0,44

Для горизонтальной прокрутки (например, карусели) заменить isCloseToBottom функция с isCloseToRight

isCloseToRight = ({ layoutMeasurement, contentOffset, contentSize }) => {
    const paddingToRight = 20;
    return layoutMeasurement.width + contentOffset.x >= contentSize.width - paddingToRight;
};
      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}
  >

Вышеуказанный ответ правильный, но для обратного вызова по достижении конца в scrollView используйте onMomentumScrollEnd, а не onScroll

Другим решением может быть использование ListView с одной строкой (ваш текст), который имеет onEndReached метод. Смотрите документацию здесь

@ Хенрик Р прав. Но вы должны использовать 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 
        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, и это сработало для меня

Вот мое решение:

Я передал опору onMomentumScrollEnd для scrollView и на основе event.nativeEvent достиг функциональности onEndReached в ScrollView

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

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

};

вы можете использовать эту функциюonMomentumScrollEndузнать информацию о прокрутке (событие)

      <ScrollView onMomentumScrollEnd={({ nativeEvent }) => {
                handleScroll(nativeEvent)
            }}>

и с этими мерами(layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom)

вы можете узнать, находится ли свиток в конце

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

игнорируйте все запутанные ответы выше. это работает.

      import React, { useState } from 'react';
import { ScrollView } from 'react-native';

function Component() {
  const [momentum, setMomentum] = useState(false)

  return (
    <ScrollView
    onMomentumScrollBegin={() => setMomentum(true)}
    onEndReached={momentum === true ? console.log('end reached.') : null}
    onEndReachedThreshold={0}
    >
      <Text>Filler Text 01</Text>
      <Text>Filler Text 02</Text>
      <Text>Filler Text 03</Text>
      <Text>Filler Text 04</Text>
      <Text>Filler Text 05</Text>
    </ScrollView>
  )
}
Другие вопросы по тегам