关于ListView下拉刷新、上拉加载更多的开源组件有很多,总结如下:
- react-native-gifted-listview 支持刷新,加载更多
- react-native-pull-to-refresh一个下拉刷新的组件,支持任意View刷新
- react-native-sk-refreshable-listview可以上下拉刷新和上拉加载的ListView
- react-native-smart-pull-to-refresh-listview支持上拉加载,下拉刷新,可以自定义的属性比较多
以上组件总结一下:太老了,并且有的还不能用,小弟又没有修改源码的能力,所以还是使用基本的ListView模拟一个比较靠谱,以后有时间再研究以上组件。
直接上代码(组织思路):
模拟使用豆瓣API(60个经典电影)
const dataUrl = 'https://api.douban.com/v2/movie/top250?count=60';
初始化设置:
constructor(props){
super(props);
const ds = new ListView.DataSource({rowHasChanged : (row1, row2) => row1 !== row2});
this.state = {
dataSource : ds,
isLoading:false,
refreshing:false,
isMoreloading:true //开始让菊花转起来
}
}
组件准备好后请求数据
componentDidMount(){
// 菊花加载
this.setState({
isLoading:true,
})
this.fetchData();
}
请求网络数据方法:
fetchData(refresh){
// 如果是下拉刷新的话,让小菊花(ActivityIndicator)一直转。。。。。
if(refresh){
this.setState({
refreshing:true
});
}
fetch(dataUrl)
.then((response) => response.json())
.then((data) => {
let dataList = data.subjects;
this.setState({
dataSource:this.state.dataSource.cloneWithRows(dataList),
isLoading:false,
refreshing:false // 关闭小菊花
})
})
.catch((err) => {
console.log(err)
})
.done()
}
render方法:
render() {
let viewList;
if(this.state.isLoading){
viewList = (
)
}else{
viewList = (
this._renderRow(data)}
refreshControl={
}
renderFooter={()=>this.renderFooter()}
onEndReached={ ()=>this._toEnd() }
/>
)
}
return (
{/*练习下拉刷新,上拉加载组件,此处渲染视图*/}
{viewList}
)
}
下拉刷新操作:
// 刷新操作
reloadNewData(){
this.fetchData(true)
}
上拉加载更多
// 上拉加载更多
renderFooter(){
if(this.state.isMoreloading){
return(
)
}else{
return(
没有更多了。
)
}
}
注意:这里利用状态isMoreloading来判断是否还有更多数据,如果有的话,就转小菊花,没有更多的话,就提示用户“没有更多了。”
滑动到最底下的时候的方法:
// 滑动到做底下的时候
_toEnd(){
setTimeout(() => {
this.setState({
isMoreloading:false
})
},2000)
}
这里模拟的是,2s后表示停止加载,没有更多数据了。
总体思路比较简单,全部代码如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableHighlight,
ListView,
RefreshControl,
ActivityIndicator
} from 'react-native';
// 顶部标题View
import NavigationBar from '../common/NavigationBar';
import Dimensions from 'Dimensions';
const {width, height} = Dimensions.get('window');
const dataUrl = 'https://api.douban.com/v2/movie/top250?count=60';
export default class BookPage extends Component {
constructor(props){
super(props);
const ds = new ListView.DataSource({rowHasChanged : (row1, row2) => row1 !== row2});
this.state = {
dataSource : ds,
isLoading:false,
refreshing:false,
isMoreloading:true
}
}
componentDidMount(){
// 菊花加载
this.setState({
isLoading:true,
})
this.fetchData();
}
fetchData(refresh){
if(refresh){
this.setState({
refreshing:true
});
}
fetch(dataUrl)
.then((response) => response.json())
.then((data) => {
let dataList = data.subjects;
this.setState({
dataSource:this.state.dataSource.cloneWithRows(dataList),
isLoading:false,
refreshing:false
})
})
.catch((err) => {
console.log(err)
})
.done()
}
_renderRow(data){
return (
{data.title}
)
}
// 刷新操作
reloadNewData(){
this.fetchData(true)
}
// 上拉加载更多
renderFooter(){
if(this.state.isMoreloading){
return(
)
}else{
return(
没有更多了。
)
}
}
// 滑动到做底下的时候
_toEnd(){
setTimeout(() => {
this.setState({
isMoreloading:false
})
},2000)
}
render() {
let viewList;
if(this.state.isLoading){
viewList = (
)
}else{
viewList = (
this._renderRow(data)}
refreshControl={
}
renderFooter={()=>this.renderFooter()}
onEndReached={ ()=>this._toEnd() }
/>
)
}
return (
{/*练习下拉刷新,上拉加载组件,此处渲染视图*/}
{viewList}
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
cellBoxStyle:{
flex: 1,
flexDirection:'row',
backgroundColor: 'white',
padding: 10,
marginLeft: 5,
marginRight: 5,
marginVertical: 3,
borderColor: '#dddddd',
borderStyle: null,
borderWidth: 0.5,
borderRadius: 2,
shadowColor: 'gray', // 设置阴影
shadowOffset: {width:0.5, height: 0.5},
shadowOpacity: 0.4, // 透明度
shadowRadius: 1,
elevation:2 // 高度,设置Z轴,可以产生立体效果
},
cellTxt:{
fontSize:16,
color:'red'
}
})