经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JSJS库框架 » JavaScript » 查看文章
react native基于FlatList下拉刷新上拉加载实现代码示例
来源:jb51  时间:2018/10/8 8:44:52  对本文有异议

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

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

下面是效果图:

ios效果图

android效果图

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

方法实现:

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

下拉刷新用的是 RefreshControl

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

具体代码:

  1. import React, { Component } from 'react';
  2. import {
  3. View,
  4. Text,
  5. Image,
  6. StyleSheet,
  7. FlatList,
  8. RefreshControl,
  9. ActivityIndicator,
  10. } from 'react-native';
  11. import { SafeAreaView } from 'react-navigation';
  12. import screnInfo from '../utils/View';
  13. import BaseStyle from '../constants/Style';
  14. import { QUESTION_LIST } from '../constants/Api';
  15. import { form_req } from '../utils/Request';
  16.  
  17. export default class TestScreen extends Component {
  18. constructor(props) {
  19. super(props);
  20. this.state = {
  21. data: [
  22. ],
  23. refreshing: false,
  24. fresh: true,
  25. animating: true,
  26. nomore: false,
  27. pageSize: 0,
  28. pageNumber: 1,
  29. };
  30. }
  31. componentDidMount() { //初始化的时候要判断长度 控制上拉加载
  32.  
  33. const ListNums = this.fullScreenJusting(50);
  34. this.setState({
  35. pageSize: ListNums
  36. })
  37. this.onEndReachedCalled = false;
  38. this.getOrderList(ListNums, 1, true);
  39.  
  40. }
  41. //满屏页面判断
  42. fullScreenJusting(ItemHeight) {
  43. const screnHeight = screnInfo.size.height; //屏幕高度
  44. //计算列表个数
  45. const listNum = (screnHeight - 40) / ItemHeight;
  46. return Math.ceil(listNum);
  47. }
  48.  
  49. getOrderList(ListNums, pageNumber, fresh) {
  50. let nomore;
  51. form_req(QUESTION_LIST, {
  52. page: pageNumber,
  53. perpage: ListNums,
  54. }).then(res => {
  55. if (res.code == 200) {
  56. const item = res.data;
  57. if (item.length < ListNums) {
  58. nomore = true
  59. } else {
  60. nomore = false
  61. }
  62. if (fresh) {
  63. this.setState({
  64. data: item,
  65. nomore: nomore
  66. })
  67. } else {
  68. this.setState({
  69. data: this.state.data.concat(item),
  70. nomore: nomore,
  71. })
  72. }
  73. // this.onEndReachedCalledDuringMomentum = true;
  74.  
  75. } else {
  76.  
  77. }
  78. });
  79. }
  80.  
  81. renderItem = item => {
  82. return (
  83. <View style={styles.item} key={item.id}>
  84. <Text>{item.name}</Text>
  85. </View>
  86. );
  87. };
  88. //列表线
  89. ItemSeparatorComponent = () => {
  90. return <View style={styles.baseLine} />;
  91. };
  92. //头部
  93. ListHeaderComponent = () => { };
  94. //尾部
  95. ListFooterComponent = () => {
  96. return (
  97. <View style={styles.bottomfoot}>
  98. {
  99. this.state.data.length != 0 ?
  100. this.state.nomore ? (
  101. <Text style={styles.footText}>- 我是有底线的 -</Text>
  102. ) : (
  103. <View style={styles.activeLoad}>
  104. <ActivityIndicator size="small" animating={this.state.animating} />
  105. <Text style={[styles.footText, styles.ml]}>加载更多...</Text>
  106. </View>
  107. )
  108. :
  109. null
  110. }
  111.  
  112. </View>
  113. );
  114. };
  115. //为空时
  116. ListEmptyComponent() {
  117. return (
  118. <View style={styles.noListView}>
  119. {/* <Image
  120. style={styles.noListImage}
  121. source={require('../images/status/order_no_record.png')}
  122. /> */}
  123. <Text style={styles.NoListText}>暂无订单</Text>
  124. </View>
  125. );
  126. }
  127. _keyExtractor = (item,index) => item.id;
  128.  
  129. _onEndReached = () => {
  130. if (!this.state.nomore && this.onEndReachedCalled ) {
  131. this.getOrderList(this.state.pageSize, ++this.state.pageNumber, false);
  132. }
  133. this.onEndReachedCalled=true;
  134.  
  135. };
  136. _onRefresh() {
  137. this.setState({ nomore: false, pageNumber: 1 }, () => {
  138. this.getOrderList(this.state.pageSize, 1, true);
  139. })
  140.  
  141. }
  142.  
  143. render() {
  144. return (
  145. <SafeAreaView style={BaseStyle.flex}>
  146. <View style={styles.listConten}>
  147. <FlatList
  148. data={this.state.data}
  149. keyExtractor={this._keyExtractor}
  150. onEndReached={this._onEndReached}
  151. refreshing={true}
  152. renderItem={({ item }) => this.renderItem(item)}
  153. ItemSeparatorComponent={this.ItemSeparatorComponent}
  154. ListEmptyComponent={this.ListEmptyComponent}
  155. ListFooterComponent={this.ListFooterComponent}
  156. onEndReachedThreshold={0.1}
  157. refreshControl={
  158. <RefreshControl
  159. refreshing={this.state.refreshing}
  160. colors={['#ff0000', '#00ff00', '#0000ff']}
  161. progressBackgroundColor={"#ffffff"}
  162. onRefresh={() => {
  163. this._onRefresh();
  164. }}
  165. />
  166. }
  167. />
  168. </View>
  169. </SafeAreaView>
  170. );
  171. }
  172. }
  173.  
  174. const styles = StyleSheet.create({
  175. listConten: {
  176. flex: 1,
  177. backgroundColor: '#ffffff',
  178. },
  179. item: {
  180. flexDirection: 'row',
  181. justifyContent: 'center',
  182. alignItems: "center",
  183. backgroundColor: '#ffffff',
  184. height: 50,
  185. },
  186. baseLine: {
  187. width: screnInfo.size.width,
  188. height: 1,
  189. backgroundColor: '#eeeeee',
  190. },
  191. noListView: {
  192. width: screnInfo.size.width,
  193. height: screnInfo.size.height - 140,
  194. justifyContent: 'center',
  195. alignItems: 'center',
  196. },
  197. NoListText: {
  198. marginTop: 15,
  199. fontSize: 18,
  200. color: '#999999',
  201. },
  202. noListImage: {
  203. width: 130,
  204. height: 140,
  205. },
  206. bottomfoot: {
  207. flexDirection: 'row',
  208. justifyContent: 'center',
  209. alignItems: 'center',
  210. padding: 10,
  211. },
  212. footText: {
  213. marginTop: 5,
  214. fontSize: 12,
  215. color: '#999999',
  216. },
  217.  
  218. activeLoad: {
  219. flexDirection: 'row',
  220. justifyContent: 'center',
  221. alignItems: 'center',
  222. },
  223. ml: {
  224. marginLeft: 10,
  225. },
  226. });

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号