react-native 模仿原生 实现下拉刷新/上拉加载更多(RefreshListView)
1.下拉刷新/上拉加载更多 组件(RefreshListView)
src/components/RefreshListView/index.js
/**
* 下拉刷新/上拉加载更多 组件(RefreshListView)
*/
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
View,
Text,
StyleSheet,
FlatList,
ActivityIndicator,
TouchableOpacity,
ViewPropTypes,
RefreshControl
} from 'react-native' const RefreshState = {
Idle: 0,
HeaderRefreshing: 1,
FooterRefreshing: 2,
NoMoreData: 3,
Failure: 4,
EmptyData: 5,
} class RefreshListView extends PureComponent {
static propTypes = {
data: PropTypes.array.isRequired,
renderItem: PropTypes.func.isRequired,
refreshState: PropTypes.number.isRequired, listRef: PropTypes.node,
onHeaderRefresh: PropTypes.func,
footerContainerStyle: ViewPropTypes.style,
footerTextStyle: ViewPropTypes.style, disabledSeparator: PropTypes.bool,
disabledHeaderRefresh: PropTypes.bool,
footerRefreshingText: PropTypes.string,
footerFailureText: PropTypes.string,
footerNoMoreDataText: PropTypes.string,
footerEmptyDataText: PropTypes.string, ListEmptyComponent: PropTypes.node,
footerRefreshingComponent: PropTypes.node,
footerFailureComponent: PropTypes.node,
footerNoMoreDataComponent: PropTypes.node,
footerEmptyDataComponent: PropTypes.node,
} static defaultProps = {
disabledHeaderRefresh: false,
footerRefreshingText: '数据加载中…',
footerFailureText: '点击重新加载',
footerNoMoreDataText: '已加载全部数据',
footerEmptyDataText: '暂时没有相关数据',
} componentWillReceiveProps(nextProps) {} componentDidUpdate(prevProps, prevState) {} onHeaderRefresh = () => {
if (this.shouldStartHeaderRefreshing()) {
this.props.onHeaderRefresh(RefreshState.HeaderRefreshing)
}
} onEndReached = () => {
if (this.shouldStartFooterRefreshing()) {
this.props.onFooterRefresh && this.props.onFooterRefresh(RefreshState.FooterRefreshing)
}
} shouldStartHeaderRefreshing = () => {
if (this.props.refreshState == RefreshState.HeaderRefreshing || this.props.refreshState == RefreshState.FooterRefreshing) {
return false
}
return true
} shouldStartFooterRefreshing = () => {
const {refreshState, data} = this.props
if (data.length == 0) {
return false
}
return (refreshState == RefreshState.Idle)
} renderSeparator = () => (
<View style={{height: 1, backgroundColor: '#e0e0e0'}} />
) renderFooter = () => {
let footer = null let {
footerRefreshingText,
footerFailureText,
footerNoMoreDataText,
footerEmptyDataText, footerRefreshingComponent,
footerFailureComponent,
footerNoMoreDataComponent,
footerEmptyDataComponent,
} = this.props switch (this.props.refreshState) {
case RefreshState.Idle: {
footer = (<View style={styles.footerContainer} />)
break
}
case RefreshState.Failure: {
footer = (
<TouchableOpacity onPress={() => {
if (this.props.data.length == 0) {
this.props.onHeaderRefresh && this.props.onHeaderRefresh(RefreshState.HeaderRefreshing)
} else {
this.props.onFooterRefresh && this.props.onFooterRefresh(RefreshState.FooterRefreshing)
}
}}
>
{footerFailureComponent ? footerFailureComponent : (
<View style={styles.footerContainer}>
<Text style={styles.footerText}>{footerFailureText}</Text>
</View>
)}
</TouchableOpacity>
)
break
}
case RefreshState.EmptyData: {
footer = (
<TouchableOpacity onPress={() => {
this.props.onHeaderRefresh && this.props.onHeaderRefresh(RefreshState.HeaderRefreshing)
}}
>
{footerEmptyDataComponent ? footerEmptyDataComponent : (
<View style={styles.footerContainer}>
<Text style={styles.footerText}>{footerEmptyDataText}</Text>
</View>
)}
</TouchableOpacity>
)
break
}
case RefreshState.FooterRefreshing: {
footer = footerRefreshingComponent ? footerRefreshingComponent : (
<View style={styles.footerContainer} >
<ActivityIndicator size="small" color="#888888" />
<Text style={[styles.footerText, {marginLeft: 7}]}>{footerRefreshingText}</Text>
</View>
)
break
}
case RefreshState.NoMoreData: {
footer = footerNoMoreDataComponent ? footerNoMoreDataComponent : (
<View style={styles.footerContainer} >
<Text style={styles.footerText}>{footerNoMoreDataText}</Text>
</View>
)
break
}
}
return footer
} render() {
const {renderItem, ...rest} = this.props
return (
<FlatList
ref={this.props.listRef}
{...rest}
// 行与行之间的分隔线组件
ItemSeparatorComponent={this.props.disabledSeparator?false:this.renderSeparator}
// 列表为空时渲染该组件
ListEmptyComponent={this.props.ListEmptyComponent}
// 头部组件
ListHeaderComponent={this.props.renderHeader}
// 尾部组件
ListFooterComponent={this.renderFooter}
// 当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用
onEndReached={this.onEndReached}
// 刷新组件
refreshControl={
this.props.disabledHeaderRefresh?false:<RefreshControl
colors={['#00ff00',"#9Bd35A", "#689F38",]}
refreshing={this.props.refreshState == RefreshState.HeaderRefreshing}
onRefresh={this.onHeaderRefresh}
/>}
// 决定当距离内容最底部还有多远时触发onEndReached回调
onEndReachedThreshold={0.1}
// 根据行数据data,渲染每一行的组件
renderItem={renderItem}
/>
)
}
} const styles = StyleSheet.create({
footerContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 10,
height: 44,
},
footerText: {
fontSize: 14,
color: '#555555',
},
}) export {
RefreshState,
} export default RefreshListView;
2.页面调用
(1)定义全局变量
// 刷新状态
global.RefreshState = {
Idle: 0, // 加载成功
HeaderRefreshing: 1, // 开始下拉刷新
FooterRefreshing: 2, // 开始上拉翻页
NoMoreData: 3, // 加载全部数据
Failure: 4, // 加载失败
EmptyData: 5, // 服务器没有数据
}
(2)通用store
@observable
refreshState: any; /**
* 改变refreshState的值
* @param refreshState
*/
@action setRefreshState(refreshState) {
this.refreshState = refreshState
}
(3)当前 store
// 加载成功
this.setRefreshState(RefreshState.Idle); if(!res.data.topics.length){
// 服务器没有数据
this.setRefreshState(RefreshState.EmptyData);
}
(4)页面
const { data, refreshState, loadData, loadMoreData } = this.store;
// 新闻列表
store = new NewsStore();
// 子组件渲染
_renderRow(obj) {
let item = obj.item;
return (
<ListRow
key={item.id}
title={item.title}
onPress={() => {
// 跳转详情页
Actions.homeDetailPage({detail: item})
}}
/>
)
}
<RefreshListView
data={toJS(data)}
keyExtractor={(item,index) => index.toString()}
renderItem={this._renderRow.bind(this)}
refreshState={refreshState}
onHeaderRefresh={loadData.bind(this.store)}
onFooterRefresh={loadMoreData.bind(this.store)}
/>
3.效果图

react-native 模仿原生 实现下拉刷新/上拉加载更多(RefreshListView)的更多相关文章
- SwipeRefreshLayout实现下拉刷新上滑加载
1. 效果图 2.RefreshLayout.java package myapplication.com.myapplication; import android.content.Context; ...
- Android 下拉刷新上啦加载SmartRefreshLayout + RecyclerView
在弄android刷新的时候,可算是耗费了一番功夫,最后发觉有现成的控件,并且非常好用,这里记录一下. 原文是 https://blog.csdn.net/huangxin112/article/de ...
- juery下拉刷新,div加载更多元素并添加点击事件(二)
buffer.append("<div class='col-xs-3 "+companyId+"' style='padding-left: 10px; padd ...
- Android如何定制一个下拉刷新,上滑加载更多的容器
前言 下拉刷新和上滑加载更多,是一种比较常用的列表数据交互方式. android提供了原生的下拉刷新容器 SwipeRefreshLayout,可惜样式不能定制. 于是打算自己实现一个专用的.但是下拉 ...
- 移动端下拉刷新上拉加载-mescroll.js插件
最近无意间看到有这么一个上拉刷新下拉加载的插件 -- mescroll.js,个人感觉挺好用的,官网地址是:http://www.mescroll.com 然后我就看了一下文档,简单的写了一个小dem ...
- Android 自定义 ListView 上下拉动“刷新最新”和“加载更多”歌曲列表
本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码 ...
- RecyclerView下拉刷新上拉加载(三)—对Adapter的封装
RecyclerView下拉刷新上拉加载(一) http://blog.csdn.net/baiyuliang2013/article/details/51506036 RecyclerView下拉刷 ...
- react-native 自定义 下拉刷新 / 上拉加载更多 组件
1.封装 Scroller 组件 /** * 下拉刷新/上拉加载更多 组件(Scroller) */ import React, {Component} from 'react'; import { ...
- vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件
vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件/库 一提到移动端的下拉刷新上拉翻页,你可能就会想到iScroll插件,没错iScroll是一个高性能,资源 ...
随机推荐
- python的加密算法(1):反转加密
说白了,就是把字符串倒序. 在js里,有一个reverse.但是python中没有. 不过,有一个更简单的方法,就是: ‘abcd’ [::-1] 这里,具体解释一下: (参看:https://doc ...
- 《锋利的JQuery》读书要点笔记1——认识JQuery&&选择器
<锋利的jQuery>源码下载,包括了这本书中全部代码以及用到的CSS文件 第一章 认识jQuery jQuery是个Js库.首先该明确的一点是:在jQuery库中$就是jQuery的一个 ...
- AC日记——[ZJOI2007]报表统计 bzoj 1058
1058 思路: 平衡树的题: 然而我的平衡树写一次炸一次QwQ: 而且各种tle: 所以stl水过: 代码: #include <set> #include <cstdio> ...
- 常用的WebService一览表
天气预报Web服务,数据来源于中国气象局Endpoint :http://www.webxml.com.cn/WebServices/WeatherWebService.asmxDisco ...
- POJ 1703 Find them, Catch them【种类/带权并查集+判断两元素是否在同一集合/不同集合/无法确定+类似食物链】
The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the ...
- 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)
layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalo ...
- Codeforces Round #394 (Div. 2) C. Dasha and Password(简单DP)
C. Dasha and Password time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- CentOS 7.1 中文正式版下载 - 最流行的免费开源企业级 Linux 服务器操作系统
如果说 Ubuntu 是现今最受桌面用户欢迎的 Linux 操作系统,那么 CentOS 就是最受公司.企业.IDC 喜爱的 Linux 发行版了.得益于极为出色的稳定性,全球范围内无数著名网站均选用 ...
- POJ 2068 Nim(博弈论)
[题目链接] http://poj.org/problem?id=2068 [题目大意] 给出两队人,交叉放置围成一圈,每个人能取的石子数有个上限,各不相同 轮流取石头,取到最后一块石头的队伍算输,问 ...
- 【周期性/容斥+二分】POJ2773-HAPPY 2006
[题目大意] 求与n互质的第k个数. [思路] 先求出小于k且与n互质的数,再利用gcd(bt+a,b)=gcd(a,b)的性质求解,效率低.枚举与n互质的数的效率是O(nlogn),求解第k个数的效 ...