React Native中ScrollView底部加载指示器名称咨询
React Native 滚动触底加载更多与底部指示器实现
核心说明
React Native 的 ScrollView 本身没有内置专属的“底部加载指示器”组件,但可以通过监听滚动事件判断是否到达底部,再自定义加载提示组件。更推荐使用专为列表场景优化的 FlatList(它继承自 ScrollView),FlatList 提供了现成的触底监听属性,能更便捷地实现加载逻辑,同时可通过 ListFooterComponent 设置底部加载指示器。
方案一:使用 FlatList 实现(推荐)
FlatList 自带 onEndReached(触底触发回调)、onEndReachedThreshold(距离底部多远触发,取值0-1,比如0.1表示距离底部10%高度时触发),以及 ListFooterComponent(设置底部加载提示)。
修改你的示例代码如下:
import React, { Component } from "react"; import { Text, Button, View, StyleSheet, FlatList, ActivityIndicator } from "react-native"; class App extends Component { state = { items: [ { item: "Item 1", price: "10", id: 1 }, { item: "Item 2", price: "20", id: 2 }, { item: "Item 3", price: "30", id: 3 }, { item: "Item 4", price: "40", id: 4 }, { item: "Item 5", price: "50", id: 5 }, { item: "Item 6", price: "60", id: 6 }, { item: "Item 7", price: "70", id: 7 }, { item: "Item 8", price: "80", id: 8 }, { item: "Item 9", price: "90", id: 9 }, { item: "Item 10", price: "100", id: 10 }, { item: "Item 11", price: "110", id: 11 }, { item: "Item 12", price: "120", id: 12 }, { item: "Item 13", price: "130", id: 13 }, { item: "Item 14", price: "140", id: 14 }, { item: "Item 15", price: "150", id: 15 }, ], isLoading: false, page: 1, }; // 模拟加载更多数据 loadMoreData = () => { if (this.state.isLoading) return; // 防止重复触发 this.setState({ isLoading: true }); // 模拟异步请求,实际项目替换为接口调用 setTimeout(() => { const newItems = Array.from({ length: 5 }, (_, i) => { const id = this.state.items.length + i + 1; return { item: `Item ${id}`, price: `${id * 10}`, id }; }); this.setState(prevState => ({ items: [...prevState.items, ...newItems], isLoading: false, page: prevState.page + 1, })); }, 1500); }; renderItem = ({ item }) => ( <View style={styles.summary}> <Text style={styles.summaryText}> {item.item} <Text style={styles.amount}>${item.price}</Text> </Text> <Button title="Order" color="#FFC107" onPress={() => { }} /> </View> ); renderFooter = () => { if (!this.state.isLoading) return null; // 自定义底部加载指示器,这里用官方ActivityIndicator组件 return ( <View style={styles.loaderContainer}> <ActivityIndicator size="large" color="#FFC107" /> <Text style={styles.loaderText}>加载中...</Text> </View> ); }; render() { return ( <View style={styles.screen}> <FlatList data={this.state.items} renderItem={this.renderItem} keyExtractor={item => item.id.toString()} onEndReached={this.loadMoreData} onEndReachedThreshold={0.1} ListFooterComponent={this.renderFooter} /> </View> ); } } // 样式定义 const styles = StyleSheet.create({ screen: { margin: 20, }, summary: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 20, padding: 10, shadowColor: "black", shadowOpacity: 0.26, shadowOffset: { width: 0, height: 2 }, shadowRadius: 8, elevation: 5, borderRadius: 10, backgroundColor: "white", }, summaryText: { fontFamily: "openSansBold", fontSize: 18, }, amount: { color: "#C2185B", }, loaderContainer: { paddingVertical: 20, alignItems: "center", }, loaderText: { marginTop: 8, fontSize: 16, color: "#666", }, }); export default App;
方案二:使用 ScrollView 实现
如果必须用ScrollView,需通过onScroll事件监听滚动位置,手动计算是否到达底部:
import React, { Component } from "react"; import { Text, Button, View, StyleSheet, ScrollView, ActivityIndicator } from "react-native"; class App extends Component { state = { items: [ { item: "Item 1", price: "10", id: 1 }, { item: "Item 2", price: "20", id: 2 }, { item: "Item 3", price: "30", id: 3 }, { item: "Item 4", price: "40", id: 4 }, { item: "Item 5", price: "50", id: 5 }, { item: "Item 6", price: "60", id: 6 }, { item: "Item 7", price: "70", id: 7 }, { item: "Item 8", price: "80", id: 8 }, { item: "Item 9", price: "90", id: 9 }, { item: "Item 10", price: "100", id: 10 }, { item: "Item 11", price: "110", id: 11 }, { item: "Item 12", price: "120", id: 12 }, { item: "Item 13", price: "130", id: 13 }, { item: "Item 14", price: "140", id: 14 }, { item: "Item 15", price: "150", id: 15 }, ], isLoading: false, }; handleScroll = (event) => { const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent; // 计算是否到达底部,预留20px偏移避免精度问题 const isReachedBottom = contentOffset.y + layoutMeasurement.height >= contentSize.height - 20; if (isReachedBottom && !this.state.isLoading) { this.loadMoreData(); } }; loadMoreData = () => { this.setState({ isLoading: true }); setTimeout(() => { const newItems = Array.from({ length: 5 }, (_, i) => { const id = this.state.items.length + i + 1; return { item: `Item ${id}`, price: `${id * 10}`, id }; }); this.setState(prevState => ({ items: [...prevState.items, ...newItems], isLoading: false, })); }, 1500); }; render() { return ( <View style={styles.screen}> <ScrollView onScroll={this.handleScroll} scrollEventThrottle={16} // 每秒触发60次,保证监听流畅 > {this.state.items.map((item) => ( <View key={item.id}> <View style={styles.summary}> <Text style={styles.summaryText}> {item.item} <Text style={styles.amount}>${item.price}</Text> </Text> <Button title="Order" color="#FFC107" onPress={() => { }} /> </View> </View> ))} {/* 底部加载指示器 */} {this.state.isLoading && ( <View style={styles.loaderContainer}> <ActivityIndicator size="large" color="#FFC107" /> <Text style={styles.loaderText}>加载中...</Text> </View> )} </ScrollView> </View> ); } } // 样式定义 const styles = StyleSheet.create({ screen: { margin: 20, }, summary: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 20, padding: 10, shadowColor: "black", shadowOpacity: 0.26, shadowOffset: { width: 0, height: 2 }, shadowRadius: 8, elevation: 5, borderRadius: 10, backgroundColor: "white", }, summaryText: { fontFamily: "openSansBold", fontSize: 18, }, amount: { color: "#C2185B", }, loaderContainer: { paddingVertical: 20, alignItems: "center", }, loaderText: { marginTop: 8, fontSize: 16, color: "#666", }, }); export default App;
关键提示
- 官方内置的加载指示器组件是
ActivityIndicator,通常作为底部加载提示的核心UI,也可以自定义文字+指示器的组合样式。 - 使用FlatList时,
onEndReachedThreshold的值可按需调整,0表示刚好滚动到底部时触发,0.1表示还有10%屏幕高度的内容未滚动时触发。 - 两种方案都需要添加
isLoading状态,防止重复触发加载请求。
内容的提问来源于stack exchange,提问作者Ibtissam
相关产品推荐
相关产品推荐

