React Native(下拉刷新,加载更多)超简单实现!

React Native轻松实现下拉刷新与加载更多功能
本文介绍了如何在React Native中实现下拉刷新和加载更多的功能。通过利用rn自带的RefreshControl处理下拉刷新,监听ScrollView的scroll事件来判断是否滑动到底部,从而触发加载更多。在iOS中,需要设置scrollEventThrottle属性以确保事件的正确触发。文中还展示了关键代码片段,如_onScroll方法中的条件判断以及如何更新状态。

我们直接进入我们今天的主题了.我们先看一下今天要实现的效果:

这里写图片描述

我们下拉的时候显示“下拉刷新状态“,当滑动到底部的时候自动显示“加载更多“。

思路:
1、下拉刷新我们直接使用rn自带的RefreshControl。
2、当我们滑动到scrollview或者listview的最底部的时候,开始显示进度条,然后加载更多。

好啦~~我们今天主要要解决的就是怎么判断scrollview或者listview滑动到最底部:

1、scrollview滑动到最顶部

搞过android的小伙伴都知道,在我们原生scrollview中,当我们的scrollview的scrollY为0的时候,即到达顶部位置,那么rn中也是一样的。

2、scrollview滑动到滑动到底部

当scrollview的高度+scrollY>=contentHeight的时候,就证明已经滑动到底部了。

好了,有了思路我们就开动了,在scrollview 中我们可以监听scroll的变化:

<ScrollView
                    refreshControl={
                         <RefreshControl
                            refreshing={this.state.isRefreshing}
                            onRefresh={this._onRefresh.bind(this)}
                            tintColor="#ff0000"
                            title="加载中..."
                            titleColor="#00ff00"
                            colors={['#ff0000', '#00ff00', '#0000ff']}
                            progressBackgroundColor="#ffffff"
                          />
                    }
                    onScroll={this._onScroll.bind(this)}
                    scrollEventThrottle={50}
                >

注意ios中一定要给scrollEventThrottle这个属性一个值,不然onScroll调用的频率会很少,影响我们的效果。

然后我们看看_onScroll方法中怎么写呢?

/**
     * scrollview滑动的时候
     * @private
     */
    _onScroll(event) {
        if(this.state.loadMore){
            return;
        }
        let y = event.nativeEvent.contentOffset.y;
        let height = event.nativeEvent.layoutMeasurement.height;
        let contentHeight = event.nativeEvent.contentSize.height;
        console.log('offsetY-->' + y);
        console.log('height-->' + height);
        console.log('contentHeight-->' + contentHeight);
        if(y+height>=contentHeight-20){
            this.setState({
                loadMore:true
            });
        }
    }

是不是soeay呢??当y+height>=contentHeight-20,这个20为我设置的一个偏移量(童鞋们可以按需求设置)。然后修改我们的state就ok了。

  render() {
        let self = this;
        return (
            <View style={styles.container}>
                {/*顶部导航栏*/}
                {self._renderNavigator()}
                <ScrollView
                    refreshControl={
                         <RefreshControl
                            refreshing={this.state.isRefreshing}
                            onRefresh={this._onRefresh.bind(this)}
                            tintColor="#ff0000"
                            title="加载中..."
                            titleColor="#00ff00"
                            colors={['#ff0000', '#00ff00', '#0000ff']}
                            progressBackgroundColor="#ffffff"
                          />
                    }
                    onScroll={this._onScroll.bind(this)}
                    scrollEventThrottle={50}
                >
                    {/*顶部菜单导航*/}
                    {self._renderTopMenus()}
                    {/*推荐商家menu1*/}
                    {self._recommendMerchant()}
                    {/*推荐商家menu1*/}
                    {self._recommendMerchant()}
                    {/*推荐商家menu1*/}
                    {self._recommendMerchant()}
                    {/*推荐商家menu1*/}
                    {self._recommendMerchant()}
                    {/*推荐商家menu1*/}
                    {self._recommendMerchant()}
                    {/*推荐商家menu1*/}
                    {self._recommendMerchant()}
                    {/*尾部上拉加载更多view*/}
                    {self._renderLoadMore()}
                </ScrollView>
            </View>
        );
    }
 /**
     * 显示上啦加载view
     * @private
     */
    _renderLoadMore() {
        if (this.state.baseDatas == null || this.state.baseDatas.recommondMerchant == null) {
            return;
        }
        return (
            <LoadingMore
                isLoading={this.state.loadMore}
                onLoading={()=>{
                    alert('fdfdfd');
                }}
            />
        );
    }

LoadingMore.js:

/**
 * @author YASIN
 * @version [React Native PABank V01,17/3/13]
 * @date 17/3/13
 * @description LoadingMore
 */
import React,{Component,PropTypes}from 'react';
import {
    View,
    ActivityIndicator,
    Text,
    TouchableOpacity
}from 'react-native';
import * as ScreenUtils from '../../Util/ScreenUtil';
import {AppBaseColor,AppBaseDimension}from '../../Constant/AppBase';
export default class LoadingMore extends Component {
    static propTypes = {
        isLoading: PropTypes.bool
    }
    static defaultProps = {
        isLoading: false
    }
    // 构造
    constructor(props) {
        super(props);
        // 初始状态
        this.state = {
            isLoading: props.isLoading
        };
    }

    render() {
        if (this.state.isLoading) {
            return (
                <View
                    style={{flexDirection:'row',alignSelf:'center',alignItems:'center',padding:ScreenUtils.scaleSize(10) }}>
                    <ActivityIndicator
                        size={'small'}
                        color={AppBaseColor.MAIN_COLOR}
                        animating={true}
                        style={{width:ScreenUtils.scaleSize(15),height:ScreenUtils.scaleSize(15)}}
                    />
                    <Text style={{
                        color:AppBaseColor.DESC_COLOR,
                        fontSize:AppBaseDimension.FontSize.DESC,
                        marginLeft:ScreenUtils.scaleSize(15)
                    }}>
                        正在加载...
                    </Text>
                </View>
            );
        } else if(this.props.onLoading){
            return (
                <TouchableOpacity
                    onPress={()=>{
                        this.setState({
                            isLoading:true
                        });
                        this.props.onLoading&&this.props.onLoading()
                    }}
                >
                    <Text style={{
                        color:AppBaseColor.DESC_COLOR,
                        fontSize:AppBaseDimension.FontSize.DESC,
                        alignSelf:'center',
                        padding:ScreenUtils.scaleSize(10)
                    }}>
                        点击加载更多...
                    </Text>
                </TouchableOpacity>
            );
        }
    }

    componentWillReceiveProps(nextProps) {
        this.setState({
            isLoading: nextProps.isLoading
        });
    }
}

ScreenUtil.js:

/**
 * @author YASIN
 * @version [Android YASIN V01, ]
 * @blog http://blog.youkuaiyun.com/vv_bug
 * @description
 * 屏幕工具类
 * ui设计基准,iphone 6
 * width:750
 * height:1334
 */
import {
    PixelRatio,
}from 'react-native';
import Dimensions from 'Dimensions';
export var screenW = Dimensions.get('window').width;
export var screenH = Dimensions.get('window').height;
var fontScale = PixelRatio.getFontScale();
export var pixelRatio =PixelRatio.get();

export const DEFAULT_DENSITY=2;
const w2 = 750/DEFAULT_DENSITY;
const h2 = 1334/DEFAULT_DENSITY;

export function setSpText(size:Number) {
    var scaleWidth = screenW / w2;
    var scaleHeight = screenH / h2;
    var scale = Math.min(scaleWidth, scaleHeight);
    size = Math.round((size * scale + 0.5) * pixelRatio / fontScale);
    return size;
}
/**
 * 屏幕适配,缩放size
 * @param size
 * @returns {Number}
 * @constructor
 */
export function scaleSize(size:Number) {
    var scaleWidth = screenW / w2;
    var scaleHeight = screenH / h2;
    var scale = Math.min(scaleWidth, scaleHeight);
    size = Math.round((size * scale + 0.5));
    return size/DEFAULT_DENSITY;
}

好啦~~! 就到这里了哦~~~

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值