FlatList基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import React from 'react'; import {SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar} from 'react-native'; const DATA = [ { id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba', title: 'First Item', }, { id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63', title: 'Second Item', }, { id: '58694a0f-3da1-471f-bd96-145571e29d72', title: 'Third Item', }, ]; const Item = ({title})=>( <View style={styles.item}> <Text style={styles.title}>{title}</Text> </View> ) const App = ()=>{ const renderItem = ({item})=>( <Item title={item.title}></Item> ) return ( <SafeAreaView style={styles.container}> <FlatList data={DATA} renderItem={renderItem} keyExtractor={item=>item.id}> </FlatList> <FlatList data={[{ title: 'Title Text', key: 'item1' }]} renderItem={({item, index, separators})=>( <TouchableHightlight onPress={()=>this._onPress(item)} onShowUnderlay={separators.hightlight} onHideUnderlay={separators.unhightlight} <View style={{backgroundColor:'white'}}> <Text>{item.title}</Text> </View> > </TouchableHightlight> )} /> </SafeAreaView> ) } const styles = StyleSheet.create({ container:{ flex: 1, marginTop: StatusBar.currentHeight || 0, }, item: { backgroundColor: '#f92cff', padding: 20, marginVertical: 8, marginHorizontal: 16, }, title: { fontSize: 32, }, })
|
StyleSheet中CSS属性遵循驼峰命名法
FlatList下拉刷新
FlatList有onRefresh
属性,如果设置了此选项,就会在列表头部添加一个标准的RefreshControl
控件,以便实现下拉刷新的功能。onRefresh是一个方法。
FlatList有refreshing
属性,在等待加载新数据时,将此属性设为true,列表就会显示出一个正在加载的符号。refreshing需要一个bool值。
FlatList上拉加载
onEndReached
属性,当列表被滚动到距离内容最底部不足onEndReachedThreshold
的距离时调用。
onEndReachedThreshold
属性,决定当距离内容最底部还有多远时触发onEndReached
回调。注意此参数是一个比值而非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。
ListFooterComponent
属性,尾部组件。
FlatList下拉刷新上拉加载步骤
- 创建RefreshState.js存放上拉加载的状态 (五个状态)
1 2 3 4 5 6 7 8
| export default { Idle: 'Idle', CanLoadMore: 'CanLoadMore', Refreshing: 'Refreshing', NoMoreData: 'NoMoreData', Failure: 'Failure' }
|
- 封装RefreshFooter组件,根据不同的状态,在列表尾部显示不同的文字信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| import React, {Component} from 'react'; import {View, Text, ActivityIndicator, StyleSheet, TouchableOpacity} from 'react-native'; import RefreshState from './RefreshState'; import PropTypes from 'prop-types';
export default class RefreshFooter extends Component{ static propTypes = { onLoadMore: PropTypes.func, onRetryLoading: PropTypes.func }; static defaultProps = { footerRefreshingText: "努力加载中", footerLoadMoreText: "上拉加载更多", footerFailureText: "点击重新加载", footerNoMoreDataText: "已全部加载完毕" }; render(){ let {state} = this.props; let footer = null; switch(state){ case RefreshState.Idle: break; case RefreshState.Refreshing: footer = <View style={styles.loadingView}> <ActivityIndicator size="small"/> <Text style={styles.refreshingText}>{this.props.footerRefreshingText}</Text> </View> break; case RefreshState.CanLoadMore: footer = <View style={styles.loadingView}> <Text style={styles.footerText}>{this.props.footerLoadMoreText}</Text> </View> break; case RefreshState.NoMoreData: footer = <View style={styles.loadingView}> <Text style={styles.footerText}>{this.props.footerNoMoreDataText}</Text> </View> break; case RefreshState.Failure: footer = <TouchableOpacity style={styles.loadingView} onPress={()=>{ this.props.onRetryLoading&&this.props.onRetryLoading(); }}> <Text style={styles.footerText}>{this.props.footerFailureText}</Text> </TouchableOpacity> break; } return footer; } } const styles = StyleSheet.create({ loadingView: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', padding: 15 }, refreshingText: { fontSize: 12, color: '#666666', paddingLeft: 10 }, footerText: { fontSize: 12, color: '#666666' } })
|
1 2 3 4
| static propTypes = { onHeaderRefresh: PropTypes.func, onFooterRefresh: PropTypes.func }
|
- 定义bool值isHeaderRefreshing作为refreshing属性的值,控制头部显示与否。定义bool值isFooterRefreshing来判断尾部组件的刷新状态。定义footerState用来设定当前尾部组件的state,作为RefreshFooter的值。
1 2 3 4 5 6 7 8
| constructor(props) { super(props); this.state = { isHeaderRefreshing: false, isFooterRefreshing: false, footerState: RefreshState.Idle, } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| render(){ return ( <FlatList {...this.props} onRefresh={()=>{this.beginHeaderRefresh()}} refreshing={this.state.isHeaderRefreshing} onEndReached={()=>{this.beginFooterRefresh()}} onEndReachedThreshold={0.1} ListFooterComponent={this._renderFooter} > </FlatList> ) _renderFooter = ()=>{ return ( <RefreshFooter state={this.state.footerState} onRetryLoading={()=>{this.beginFooterRefresh()}} /> ) } }
|
- beginHeaderRefresh和beginFooterRefresh两个方法用来调用刷新的,但是刷新之前还需要做逻辑处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| beginHeaderRefresh(){ if(this.shouldStartHeaderRefreshing()){ this.startHeaderRefreshing(); } }
beginFooterRefresh(){ if(this.shouldStartFooterRefreshing()){ this.startFooterRefreshing(); } }
shouldStartHeaderRefreshing(){ if(this.state.footerState===RefreshState.Refreshing|| this.state.isHeaderRefreshing|| this.state.isFooterRefreshing) return false; return true; }
shouldStartFooterRefreshing(){ if(this.state.footerState===RefreshState.Refreshing|| this.state.footerState===RefreshState.NoMoreData|| this.props.data.length===0|| this.state.isHeaderRefreshing|| this.state.isFooterRefreshing) return false; return true; } startHeaderRefreshing(){ this.setState({ isHeaderRefreshing: true }, ()=>{ this.props.onHeaderRefresh&&this.props.onHeaderRefresh(); }) } startFooterRefreshing(){ this.setState({ isFooterRefreshing: true, footerState: RefreshState.Refreshing }, ()=>{ this.props.onFooterRefresh&&this.props.onFooterRefresh() }) }
|
1 2 3 4 5 6 7 8 9 10
| endRefreshing(footerState){ let footerRefreshState = footerState; if(this.props.data.length===0) footerRefreshState = RefreshState.Idle; this.setState({ footerState: footerRefreshState, isHeaderRefreshing: false, isFooterRefreshing: false }) }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| loadData(){ let that = this; fetch(queryData('beijing', this.state.startPage, this.state.pageSize).then(res=>{ let res1 = res.data; let totalCount = res.total; let currentCount = this.state.data.length; let footerState = RefreshState.Idle; let startPage = this.state.startPage; if(currentCount+res1<totalCount){ footerState=RefreshState.CanLoadMore; startPage += 1; }else footerState=RefreshState.NoMoreData; this.setState({data: [...data, res1], startPage}); this.listView.endRefreshing(footerState); })).catch(e=>{ that.listView.endRefreshing(RefreshState.Failure); }) }
|
总结
定义尾组件的状态**—–>封装RefreshFooter尾组件—–>通过onRefresh(方法)、refreshing(bool)、onEndReached、onEndReachedThreshold、ListFooterComponent封装RefreshListView组件,在该组件中定义三个状态,分别用于表示头组件、尾组件是否在刷新、尾组件当前状态,定义方法来判断头组件和尾组件是否需要执行更新,如果需要则调用父组件中传入的数据更新方法,更新完毕后修改组件状态来结束更新—->**在父组件中调用RefreshListView组件同时定义获取数据的方式