JavaScript

超轻量级php框架startmvc

react native基于FlatList下拉刷新上拉加载实现代码示例

更新时间:2020-07-30 23:06:01 作者:startmvc
reactnative的上拉加载一直困扰着自己,一直用的第三方组件,但是可维护性不高,而且也不

react native 的上拉加载一直困扰着自己,一直用的第三方组件,但是可维护性不高,而且也不太好用,最近工作没那么忙,就研究下了官方的FlatList,做出来的成果,比第三方组件流畅度高好多,而且也很好用

官方介绍:https://reactnative.cn/docs/flatlist/

下面是效果图:

ios效果图

android效果图

总体思路就是:就是计算屏幕高度,然后减去导航的头部,根据列表高度计算出每页的个数,然后向上取整。这样做的目的是:防止不满屏状态下的,onEndReached函数的主动触发。

方法实现:


 //满屏页面判断
 fullScreenJusting(ItemHeight) {
 const screnHeight = screnInfo.size.height; //屏幕高度
 //计算列表个数
 const listNum = (screnHeight - 40) / ItemHeight;
 return Math.ceil(listNum);
 }

下拉刷新用的是 RefreshControl

官网地址:https://reactnative.cn/docs/refreshcontrol/#progressbackgroundcolor

具体代码:


import React, { Component } from 'react';
import {
 View,
 Text,
 Image,
 StyleSheet,
 FlatList,
 RefreshControl,
 ActivityIndicator,
} from 'react-native';
import { SafeAreaView } from 'react-navigation';
import screnInfo from '../utils/View';
import BaseStyle from '../constants/Style';
import { QUESTION_LIST } from '../constants/Api';
import { form_req } from '../utils/Request';

export default class TestScreen extends Component {
 constructor(props) {
 super(props);
 this.state = {
 data: [
 ],
 refreshing: false,
 fresh: true,
 animating: true,
 nomore: false,
 pageSize: 0,
 pageNumber: 1,
 };
 }
 componentDidMount() { //初始化的时候要判断长度 控制上拉加载

 const ListNums = this.fullScreenJusting(50);
 this.setState({
 pageSize: ListNums
 })
 this.onEndReachedCalled = false;
 this.getOrderList(ListNums, 1, true);

 }
 //满屏页面判断
 fullScreenJusting(ItemHeight) {
 const screnHeight = screnInfo.size.height; //屏幕高度
 //计算列表个数
 const listNum = (screnHeight - 40) / ItemHeight;
 return Math.ceil(listNum);
 }

 getOrderList(ListNums, pageNumber, fresh) {
 let nomore;
 form_req(QUESTION_LIST, {
 page: pageNumber,
 perpage: ListNums,
 }).then(res => {
 if (res.code == 200) {
 const item = res.data;
 if (item.length < ListNums) {
 nomore = true
 } else {
 nomore = false
 }
 if (fresh) {
 this.setState({
 data: item,
 nomore: nomore
 })
 
 } else {
 this.setState({
 data: this.state.data.concat(item),
 nomore: nomore,
 })
 }
 // this.onEndReachedCalledDuringMomentum = true;

 } else {

 }
 });
 }

 renderItem = item => {
 return (
 <View style={styles.item} key={item.id}>
 <Text>{item.name}</Text>
 </View>
 );
 };
 //列表线
 ItemSeparatorComponent = () => {
 return <View style={styles.baseLine} />;
 };
 //头部
 ListHeaderComponent = () => { };
 //尾部
 ListFooterComponent = () => {
 return (
 <View style={styles.bottomfoot}>
 {
 this.state.data.length != 0 ?
 this.state.nomore ? (
 <Text style={styles.footText}>- 我是有底线的 -</Text>
 ) : (
 <View style={styles.activeLoad}>
 <ActivityIndicator size="small" animating={this.state.animating} />
 <Text style={[styles.footText, styles.ml]}>加载更多...</Text>
 </View>
 )
 :
 null
 }

 </View>
 );
 };
 //为空时
 ListEmptyComponent() {
 return (
 <View style={styles.noListView}>
 {/* <Image
 style={styles.noListImage}
 source={require('../images/status/order_no_record.png')}
 /> */}
 <Text style={styles.NoListText}>暂无订单</Text>
 </View>
 );
 }
 _keyExtractor = (item,index) => item.id;

 _onEndReached = () => {
 if (!this.state.nomore && this.onEndReachedCalled ) {
 this.getOrderList(this.state.pageSize, ++this.state.pageNumber, false);
 }
 this.onEndReachedCalled=true;

 };
 _onRefresh() {
 this.setState({ nomore: false, pageNumber: 1 }, () => {
 this.getOrderList(this.state.pageSize, 1, true);
 })

 }

 render() {
 return (
 <SafeAreaView style={BaseStyle.flex}>
 <View style={styles.listConten}>
 <FlatList
 data={this.state.data}
 keyExtractor={this._keyExtractor}
 onEndReached={this._onEndReached}
 refreshing={true}
 renderItem={({ item }) => this.renderItem(item)}
 ItemSeparatorComponent={this.ItemSeparatorComponent}
 ListEmptyComponent={this.ListEmptyComponent}
 ListFooterComponent={this.ListFooterComponent}
 onEndReachedThreshold={0.1}
 refreshControl={
 <RefreshControl
 refreshing={this.state.refreshing}
 colors={['#ff0000', '#00ff00', '#0000ff']}
 progressBackgroundColor={"#ffffff"}
 onRefresh={() => {
 this._onRefresh();
 }}
 />
 }
 />
 </View>
 </SafeAreaView>
 );
 }
}

const styles = StyleSheet.create({
 listConten: {
 flex: 1,
 backgroundColor: '#ffffff',
 },
 item: {
 flexDirection: 'row',
 justifyContent: 'center',
 alignItems: "center",
 backgroundColor: '#ffffff',
 height: 50,
 },
 baseLine: {
 width: screnInfo.size.width,
 height: 1,
 backgroundColor: '#eeeeee',
 },
 noListView: {
 width: screnInfo.size.width,
 height: screnInfo.size.height - 140,
 justifyContent: 'center',
 alignItems: 'center',
 },
 NoListText: {
 marginTop: 15,
 fontSize: 18,
 color: '#999999',
 },
 noListImage: {
 width: 130,
 height: 140,
 },
 bottomfoot: {
 flexDirection: 'row',
 justifyContent: 'center',
 alignItems: 'center',
 padding: 10,
 },
 footText: {
 marginTop: 5,
 fontSize: 12,
 color: '#999999',
 },

 activeLoad: {
 flexDirection: 'row',
 justifyContent: 'center',
 alignItems: 'center',
 },
 ml: {
 marginLeft: 10,
 },
});

这里的坑就是:当初始化进来页面的时候 上拉会主动触发,所以这里加了一个开关 this.onEndReachedCalled = false; 初始化给一个false 当触发了 设为true,放在调取接口之后

代码都很简单易懂~ 有什么不懂的,或者有什么问题请留言,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

reactnative FlatList 上拉加载 reactnative FlatList 下拉刷新 reactnative FlatList