react native基于FlatList下拉刷新上拉加载实现代码示例
程序员文章站
2022-07-04 17:38:33
react native 的上拉加载一直困扰着自己,一直用的第三方组件,但是可维护性不高,而且也不太好用,最近工作没那么忙,就研究下了官方的flatlist,做出来的成果,...
react native 的上拉加载一直困扰着自己,一直用的第三方组件,但是可维护性不高,而且也不太好用,最近工作没那么忙,就研究下了官方的flatlist,做出来的成果,比第三方组件流畅度高好多,而且也很好用
官方介绍:
下面是效果图:
ios效果图
android效果图
总体思路就是:就是计算屏幕高度,然后减去导航的头部,根据列表高度计算出每页的个数,然后向上取整。这样做的目的是:防止不满屏状态下的,onendreached函数的主动触发。
方法实现:
//满屏页面判断 fullscreenjusting(itemheight) { const screnheight = screninfo.size.height; //屏幕高度 //计算列表个数 const listnum = (screnheight - 40) / itemheight; return math.ceil(listnum); }
下拉刷新用的是 refreshcontrol
官网地址:
具体代码:
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,放在调取接口之后
代码都很简单易懂~ 有什么不懂的,或者有什么问题请留言,希望对大家的学习有所帮助,也希望大家多多支持。