废话不多说,自己的项目都是用这个写的
直接放出源码,
如果对你有用,请大家给个喜欢.
/**
* @memberOf RefreshListView 皓天
* */
import React, {PureComponent} from 'react'
import {View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity} from 'react-native'
export const RefreshState = {
Idle: 0,
HeaderRefreshing: 1,
FooterRefreshing: 2,
NoMoreData: 3,
Failure: 4,
}
const DEBUG = false
const log = (text: string) => {DEBUG && console.log(text)}
type Props = {
refreshState: number,
onHeaderRefresh: (refreshState: number) => void,
onFooterRefresh?: (refreshState: number) => void,
data: Array<any>,
footerContainerStyle?: any,
footerTextStyle?: any,
listRef?: any,
footerRefreshingText?: string,
footerFailureText?: string,
footerNoMoreDataText?: string,
}
class RefreshListView extends PureComponent {
props: Props
static defaultProps = {
footerRefreshingText: '数据加载中…',
footerFailureText: '点击重新加载',
footerNoMoreDataText: '已加载全部数据',
}
componentWillReceiveProps(nextProps: Props) {
log('[RefreshListView] RefreshListView componentWillReceiveProps ' + nextProps.refreshState)
}
componentDidUpdate(prevProps: Props, prevState: State) {
log('[RefreshListView] RefreshListView componentDidUpdate ' + prevProps.refreshState)
}
onHeaderRefresh = () => {
log('[RefreshListView] onHeaderRefresh')
if (this.shouldStartHeaderRefreshing()) {
log('[RefreshListView] onHeaderRefresh')
this.props.onHeaderRefresh(RefreshState.HeaderRefreshing)
}
}
onEndReached = (info: any) => {
log('[RefreshListView] onEndReached ' + info.distanceFromEnd)
if (this.shouldStartFooterRefreshing()) {
log('[RefreshListView] onFooterRefresh')
this.props.onFooterRefresh && this.props.onFooterRefresh(RefreshState.FooterRefreshing)
}
}
shouldStartHeaderRefreshing = () => {
log('[RefreshListView] shouldStartHeaderRefreshing')
if (this.props.refreshState == RefreshState.HeaderRefreshing ||
this.props.refreshState == RefreshState.FooterRefreshing) {
return false
}
return true
}
shouldStartFooterRefreshing = () => {
log('[RefreshListView] shouldStartFooterRefreshing')
let {refreshState, data} = this.props
if (data.length == 0) {
return false
}
return (refreshState == RefreshState.Idle)
}
render() {
log('[RefreshListView] render')
return (
<FlatList
ref={this.props.listRef}
onEndReached={this.onEndReached}
onRefresh={this.onHeaderRefresh}
refreshing={this.props.refreshState == RefreshState.HeaderRefreshing}
ListFooterComponent={this.renderFooter}
onEndReachedThreshold={0.1}
{...this.props}
/>
)
}
renderFooter = () => {
let footer = null
let footerContainerStyle = [styles.footerContainer, this.props.footerContainerStyle]
let footerTextStyle = [styles.footerText, this.props.footerTextStyle]
let {footerRefreshingText, footerFailureText, footerNoMoreDataText} = this.props
switch (this.props.refreshState) {
case RefreshState.Idle:
footer = (<View style={footerContainerStyle} />)
break
case RefreshState.Failure: {
footer = (
<TouchableOpacity
style={footerContainerStyle}
onPress={() => {
this.props.onFooterRefresh && this.props.onFooterRefresh(RefreshState.FooterRefreshing)
}}
>
<Text style={footerTextStyle}>{footerFailureText}</Text>
</TouchableOpacity>
)
break
}
case RefreshState.FooterRefreshing: {
footer = (
<View style={footerContainerStyle} >
<ActivityIndicator size="small" color="#888888" />
<Text style={[footerTextStyle, {marginLeft: 7}]}>{footerRefreshingText}</Text>
</View>
)
break
}
case RefreshState.NoMoreData: {
footer = (
<View style={footerContainerStyle} >
<Text style={footerTextStyle}>{footerNoMoreDataText}</Text>
</View>
)
break
}
}
return footer
}
}
const styles = StyleSheet.create({
footerContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 10,
height: 44,
},
footerText: {
fontSize: 14,
color: '#555555',
}
})
export default RefreshListView
下面是使用方法,
介于很多小白看不懂,所以代码全部放出.如果你连调用都看不懂的话,请下面
回复,我看到了会解答的.
具体的实现内容我删掉了很多项目中的代码.
上啦和下拉的基本都在这,剩下的就是一些业务逻辑了.
你可以直接套用
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet, Text,
View, FlatList, ScrollView, TextInput,
Image, TouchableOpacity, InteractionManager, Platform
} from 'react-native';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import store, { persistStore } from '../../store'
import * as actions from '../../actions'
import RefreshListView, { RefreshState } from '../../components/common/RefreshListView'
class FindSearch extends Component {
//这里一定要定义
state: {
dataList: Array<any>,
refreshState: number,
}
static navigationOptions = {
header: null,
};
constructor(props) {
super(props)
}
componentDidMount() {
// store.dispatch(resetState());
}
/**
*
* 每一行数据
*
* @memberOf FindSearch
*/
_renderItem = (item, index) => {
return (
<Text>每一行数据</Text>
)
}
keyExtractor = (item, index) => index;
//下拉刷新
onHeaderRefresh = () => {
this.setState({ refreshState: RefreshState.HeaderRefreshing })
//获取测试数据
var id = this.props.navigation.state.params.id
let url = HOME_COMMENTAR_DETAILS + id + '/1'
request(url, 'GET', (responseData: Object) => {
// console.log(responseData + ' 点赞返回值')
this.setState({
refreshState: RefreshState.Idle,
data:这里直接更新数组
})
numberString = 1
}, {}, null, true, true);
this.setState({
refreshState: RefreshState.Idle,
})
}
//上啦刷新
onFooterRefresh = () => {
//这行代码必写
this.setState({ refreshState: RefreshState.FooterRefreshing })
/**
*
* 很多Demo 都是用本地数据,可能会出现很多问题.
* 我这里直接放出网络数据,大家可以直接按照我的写就行了
* request()是我自己的封装,不能放出.
*/
numberString += 1
//获取数据
var id = this.props.navigation.state.params.id
let url = HOME_COMMENTAR_DETAILS + id + '/' + numberString
request(url, 'GET', (responseData: Object) => {
console.log(responseData + ' 点赞返回值')
if (responseData.length == 0) {
this.setState({
refreshState: RefreshState.NoMoreData
})
} else{
//这里更新state
this.setState({
data:这里是列表的数组
refreshState: RefreshState.NoMoreData
})
}
}, {}, null, true, true);
}
render() {
<RefreshListView
ref='flatlist'
extraData={this.state}
data={findsearch.findsearchlist}//这里我使用了redux 其实就是个数组
keyExtractor={this.keyExtractor}
renderItem={this._renderItem}
refreshState={this.state.refreshState}
onHeaderRefresh={this.onHeaderRefresh}
onFooterRefresh={this.onFooterRefresh}
removeClippedSubviews={false}
// 可选
footerRefreshingText='玩命加载中 >.<'
footerFailureText='我擦嘞,居然失败了 =.=!'
footerNoMoreDataText='-我是有底线的-'
/>
}
const styles = StyleSheet.create({
container: {
width: 100,
height: 100,
borderRadius: 10
},
})
function mapStateToProps(state) {
let { screen, object, account, findsearch } = state
return {
screen,
object,
account,
findsearch,
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(actions, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(FindSearch)