Определить 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 было равно нулю.
Поскольку люди помогли здесь, я добавлю простой код, который они пишут, чтобы событие достигло верха и низа, и я сделал небольшую иллюстрацию, чтобы сделать вещи проще
<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>
)
}