React-Native 使用 Flatlist 滚动到顶部
React-Native scroll to top with Flatlist
我在滚动到 Flatlist 的顶部时遇到了很多问题,因此非常感谢您的帮助!
基本上它从 firebase 获取前 5 个项目,然后在调用 onEndReached 时我们将接下来的 5 个项目附加到列表中:
data: [...this.state.data, ...results]
现在我的视图顶部有一个刷新按钮,它执行以下操作:
this.flatListRef.scrollToOffset({ animated: true, y: 0 });
如果我在呈现前 5 个项目时单击此按钮,它将按预期滚动到列表顶部。该问题仅在列表附加到(我猜这些项目不在视图中?)后才会出现。
我也试过 'ScrollToItem' 但是我猜这行不通是因为 React Native 文档中的以下内容:
Note: Cannot scroll to locations outside the render window without
specifying the getItemLayout prop.
任何人都可以解释发生了什么或知道我做错了什么吗?
提前致谢!
getItemLayout:(不完全确定这是做什么的或如何计算长度和偏移量等)
getItemLayout = (data, index) => (
{ length: 50, offset: 50 * index, index }
)
return (
<View>
<FlatList
ref={(ref) => { this.flatListRef = ref; }}
onScroll={this.handleScroll}
data={this.state.data}
keyExtractor={item => item.key}
ListFooterComponent={this.renderFooter()}
onRefresh={this.handleRefresh}
refreshing={this.state.newRefresh}
onEndReached={this.handleEndRefresh}
onEndReachedThreshold={0.05}
getItemLayout={this.getItemLayout}
renderItem={this.renderItem}
/>
{this.state.refreshAvailable ? this.renderRefreshButton() : null}
</View>
);
正确的语法是
this.flatListRef.scrollToOffset({ animated: true, offset: 0 });
你也可以使用
以防万一有人不知道如何使用钩子来做到这一点,这里有一个例子
function MyComponent() {
const flatListRef = React.useRef()
const toTop = () => {
// use current
flatListRef.current.scrollToOffset({ animated: true, offset: 0 })
}
return (
<FlatList
ref={flatListRef}
data={...}
...
/>
)
}
主要区别在于您可以通过 .current
访问它
对于反应钩子
import React, {useRef} from 'react'
- 声明它 ->
const flatListRef = useRef()
- 设置为
ref={flatListRef}
- 可以这样称呼它
flatListRef.current.scrollToOffset({animated: false, offset: 0})
在这个回答中,我提到了一个非常简单的代码片段,其中有 2 个按钮可以向右或向左滚动 flatlist。您可以使用此代码实现编程滚动平面列表的其他用例。
//import
import React, { useEffect, useState, useRef, useCallback } from 'react';
//React class declaration.
const DocumentsInfo = ({ route, navigation }) => {
//state variable
const [documentsArray, setDocumentsArray] = useState({}); // array being shown in flatlist.
const [maxVisibleIndex, setMaxVisibleIndex] = useState(0); // highest visible index currently visible.
const [minVisibleIndex, setMinVisibleIndex] = useState(0); // lowest visible index currently visible.
const flatListRef = useRef() // reference of flatlist.
// callback for whenever flatlist scrolls
const _onViewableItemsChanged = useCallback(({ viewableItems, changed }) => {
setMaxVisibleIndex(viewableItems[viewableItems.length - 1].index);
setMinVisibleIndex(viewableItems[0].index);
}, []);
// function for scrolling to top
const scrollToTop = () => {
setMinVisibleIndex(0);
setMaxVisibleIndex(0);
flatListRef.current.scrollToIndex({ index: 0, animated: true });
};
// function for scrolling to bottom
const scrollToBottom = () => {
let temp = documentsArray.length - 1;
setMinVisibleIndex(temp);
setMaxVisibleIndex(temp);
flatListRef.current.scrollToIndex({ index: temp, animated: true });
};
// function for moving flatlist left and right by 1 index
const moveNextPreviousHorizontalFlatlist = (isNext) => {
if (isNext) {
let maxVisible = maxVisibleIndex + 1;
if (maxVisible < documentsArray.length) {
let minVisible = minVisibleIndex + 1;
setMinVisibleIndex(minVisible);
setMaxVisibleIndex(maxVisible);
flatListRef.current.scrollToIndex({ index: maxVisible, animated: true });
}
}
else {
let minVisible = minVisibleIndex - 1;
if (minVisible >= 0) {
let maxVisible = maxVisibleIndex - 1;
setMinVisibleIndex(minVisible);
setMaxVisibleIndex(maxVisible);
flatListRef.current.scrollToIndex({ index: minVisible, animated: true });
}
}
};
// UI
return (
<View>
{ maxVisibleIndex != documentsArray.length - 1 &&
<View style={styles.Refresh}>
<TouchableOpacity onPress={() =>
moveNextPreviousHorizontalFlatlist(true)
}>
<Image style={styles.Refresh} source={Refresh} />
</TouchableOpacity>
</View>
}
<FlatList
ref={flatListRef}
onViewableItemsChanged={_onViewableItemsChanged}
showsHorizontalScrollIndicator={false}
horizontal
keyExtractor={(item, index) => item.fileName + index}
data={documentsArray}
renderItem={({ item, index }) => {
return ( <DocumentListItem /> )
}}
/>
{ minVisibleIndex != 0 &&
<View style={styles.Refresh}>
<TouchableOpacity onPress={() =>
moveNextPreviousHorizontalFlatlist(false)
}>
<Image style={styles.Refresh} source={Refresh} />
</TouchableOpacity>
</View>
}
</View>
);
我在滚动到 Flatlist 的顶部时遇到了很多问题,因此非常感谢您的帮助!
基本上它从 firebase 获取前 5 个项目,然后在调用 onEndReached 时我们将接下来的 5 个项目附加到列表中:
data: [...this.state.data, ...results]
现在我的视图顶部有一个刷新按钮,它执行以下操作:
this.flatListRef.scrollToOffset({ animated: true, y: 0 });
如果我在呈现前 5 个项目时单击此按钮,它将按预期滚动到列表顶部。该问题仅在列表附加到(我猜这些项目不在视图中?)后才会出现。
我也试过 'ScrollToItem' 但是我猜这行不通是因为 React Native 文档中的以下内容:
Note: Cannot scroll to locations outside the render window without specifying the getItemLayout prop.
任何人都可以解释发生了什么或知道我做错了什么吗?
提前致谢!
getItemLayout:(不完全确定这是做什么的或如何计算长度和偏移量等)
getItemLayout = (data, index) => (
{ length: 50, offset: 50 * index, index }
)
return (
<View>
<FlatList
ref={(ref) => { this.flatListRef = ref; }}
onScroll={this.handleScroll}
data={this.state.data}
keyExtractor={item => item.key}
ListFooterComponent={this.renderFooter()}
onRefresh={this.handleRefresh}
refreshing={this.state.newRefresh}
onEndReached={this.handleEndRefresh}
onEndReachedThreshold={0.05}
getItemLayout={this.getItemLayout}
renderItem={this.renderItem}
/>
{this.state.refreshAvailable ? this.renderRefreshButton() : null}
</View>
);
正确的语法是
this.flatListRef.scrollToOffset({ animated: true, offset: 0 });
你也可以使用
以防万一有人不知道如何使用钩子来做到这一点,这里有一个例子
function MyComponent() {
const flatListRef = React.useRef()
const toTop = () => {
// use current
flatListRef.current.scrollToOffset({ animated: true, offset: 0 })
}
return (
<FlatList
ref={flatListRef}
data={...}
...
/>
)
}
主要区别在于您可以通过 .current
对于反应钩子
import React, {useRef} from 'react'
- 声明它 ->
const flatListRef = useRef()
- 设置为
ref={flatListRef}
- 可以这样称呼它
flatListRef.current.scrollToOffset({animated: false, offset: 0})
在这个回答中,我提到了一个非常简单的代码片段,其中有 2 个按钮可以向右或向左滚动 flatlist。您可以使用此代码实现编程滚动平面列表的其他用例。
//import
import React, { useEffect, useState, useRef, useCallback } from 'react';
//React class declaration.
const DocumentsInfo = ({ route, navigation }) => {
//state variable
const [documentsArray, setDocumentsArray] = useState({}); // array being shown in flatlist.
const [maxVisibleIndex, setMaxVisibleIndex] = useState(0); // highest visible index currently visible.
const [minVisibleIndex, setMinVisibleIndex] = useState(0); // lowest visible index currently visible.
const flatListRef = useRef() // reference of flatlist.
// callback for whenever flatlist scrolls
const _onViewableItemsChanged = useCallback(({ viewableItems, changed }) => {
setMaxVisibleIndex(viewableItems[viewableItems.length - 1].index);
setMinVisibleIndex(viewableItems[0].index);
}, []);
// function for scrolling to top
const scrollToTop = () => {
setMinVisibleIndex(0);
setMaxVisibleIndex(0);
flatListRef.current.scrollToIndex({ index: 0, animated: true });
};
// function for scrolling to bottom
const scrollToBottom = () => {
let temp = documentsArray.length - 1;
setMinVisibleIndex(temp);
setMaxVisibleIndex(temp);
flatListRef.current.scrollToIndex({ index: temp, animated: true });
};
// function for moving flatlist left and right by 1 index
const moveNextPreviousHorizontalFlatlist = (isNext) => {
if (isNext) {
let maxVisible = maxVisibleIndex + 1;
if (maxVisible < documentsArray.length) {
let minVisible = minVisibleIndex + 1;
setMinVisibleIndex(minVisible);
setMaxVisibleIndex(maxVisible);
flatListRef.current.scrollToIndex({ index: maxVisible, animated: true });
}
}
else {
let minVisible = minVisibleIndex - 1;
if (minVisible >= 0) {
let maxVisible = maxVisibleIndex - 1;
setMinVisibleIndex(minVisible);
setMaxVisibleIndex(maxVisible);
flatListRef.current.scrollToIndex({ index: minVisible, animated: true });
}
}
};
// UI
return (
<View>
{ maxVisibleIndex != documentsArray.length - 1 &&
<View style={styles.Refresh}>
<TouchableOpacity onPress={() =>
moveNextPreviousHorizontalFlatlist(true)
}>
<Image style={styles.Refresh} source={Refresh} />
</TouchableOpacity>
</View>
}
<FlatList
ref={flatListRef}
onViewableItemsChanged={_onViewableItemsChanged}
showsHorizontalScrollIndicator={false}
horizontal
keyExtractor={(item, index) => item.fileName + index}
data={documentsArray}
renderItem={({ item, index }) => {
return ( <DocumentListItem /> )
}}
/>
{ minVisibleIndex != 0 &&
<View style={styles.Refresh}>
<TouchableOpacity onPress={() =>
moveNextPreviousHorizontalFlatlist(false)
}>
<Image style={styles.Refresh} source={Refresh} />
</TouchableOpacity>
</View>
}
</View>
);