视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
react native基于FlatList下拉刷新上拉加载实现代码示例
2020-11-27 22:06:49 责编:小采
文档


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

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

下载本文
显示全文
专题