首页 > 编程 > JavaScript > 正文

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

2019-11-19 12:48:35
字体:
来源:转载
供稿:网友

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,放在调取接口之后

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表