react native封装ScrollView,实现(滑到底部)和(滑到顶部+手指继续向下滑)时拉取新数据

里面的tw是在react native中使用tailwind的第三方库
只求读者把样式看个大概,主要还是功能的实现
ScrollView的官方文档如下
https://reactnative.cn/docs/scrollview

import tw from 'twrnc'
import { View, Text, ScrollView, RefreshControl } from 'react-native'
import { useState, useEffect } from 'react'

const MyScrollView = ({ }) => {
    const [data, setData] = useState([]);
    const [refreshing, setRefreshing] = useState(false);

    const handleTopRefresh = () => {
        // 防抖
        if (refreshing === false) {
            setRefreshing(true);
            console.log("触发上拉刷新")
            setTimeout(() => {
                console.log("拿到新数据")
                setRefreshing(false);
            }, 1500);
        }
    };

    const handleBottomRefresh = (e) => {
        // 防抖
        if (refreshing === false) {
            const offsetY = e.nativeEvent.contentOffset.y; //滑动距离
            const contentSizeHeight = e.nativeEvent.contentSize.height; //scrollView contentSize高度
            const scrollHeight = e.nativeEvent.layoutMeasurement.height; //scrollView高度
            //似乎有时会有误差,比如滑到底部但是(755.9999771118164<756),我的解决思路是取ceil
            if (Math.ceil(offsetY + scrollHeight) >= contentSizeHeight) {
                console.log("触发底部刷新")
                setRefreshing(true);
                setTimeout(() => {
                    console.log("拿到新数据")
                    setRefreshing(false);
                }, 1500);
            }
        }
    }

    useEffect(() => {
        const res = [];
        for (let i = 0; i < 19; i++) {
            res.push(i);
        }
        setData(res);
    }, [])

    return (
        <ScrollView
            refreshControl={
                <RefreshControl refreshing={refreshing} onRefresh={handleTopRefresh} />
            }
            onMomentumScrollEnd={handleBottomRefresh}
            style={tw`flex-1`}>
            <View style={tw`gap-1 `}>
                {data.map((item, idx) => (
                    <Text style={tw`text-center text-3xl bg-yellow-200`} key={idx}>{item}</Text>
                ))
                }
            </View>
        </ScrollView>
    )
}

export default MyScrollView;

演示动画注意看终端里的输出
在这里插入图片描述

顺便看到了一个Toast组件,直接拿来当做加载后的提示了
https://github.com/calintamas/react-native-toast-message/tree/main
在这里插入图片描述


秉持着不水短文章的做法,附加上我自己写的白屏加载组件
Modal应该是absolute的组件,所以这个组件放哪都行
这里我查资料的时候才知道官方有写好了加载动画组件

import tw from 'twrnc'
import { View, Modal, ActivityIndicator } from 'react-native'

const Loading = ({ visible = false }) => {
    return (
        <Modal visible={visible} transparent={true}>
            <View style={tw`bg-white opacity-80 h-full w-full items-center justify-center`}>
                <ActivityIndicator size="large" color="#0000ff" />
            </View>
        </Modal>
    )
}

export default Loading;

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Native中,当一个ScrollView嵌套在另一个ScrollView中时,子ScrollView默认是不可以动的。为了让子ScrollView可以动,需要在父ScrollView的onTouchStart、onTouchMove和onTouchEnd事件中对事件进行处理。 具体来说,可以在父ScrollView的onTouchStart事件中记录下当前手指的位置,然后在onTouchMove事件中判断当前手指的位置是否在子ScrollView的范围内,如果是,则将事件交给子ScrollView处理;如果不是,则将事件交给父ScrollView处理。在onTouchEnd事件中,可以清除掉已经记录的手指位置信息。 以下是一个示例代码: ``` import React, { Component } from 'react'; import { ScrollView, View } from 'react-native'; class ParentScrollView extends Component { constructor(props) { super(props); this.state = { isChildScrolling: false, childScrollTop: 0, }; } handleChildScroll = (event) => { const { contentOffset } = event.nativeEvent; this.setState({ childScrollTop: contentOffset.y, }); } handleTouchStart = (event) => { const { locationY } = event.nativeEvent; if (locationY > this.state.childScrollTop) { this.setState({ isChildScrolling: true, }); } } handleTouchMove = (event) => { const { locationY } = event.nativeEvent; if (this.state.isChildScrolling) { this.childScrollView.scrollTo({ y: locationY - this.state.childScrollTop }); } } handleTouchEnd = () => { this.setState({ isChildScrolling: false, childScrollTop: 0, }); } render() { return ( <ScrollView onTouchStart={this.handleTouchStart} onTouchMove={this.handleTouchMove} onTouchEnd={this.handleTouchEnd} > <View style={{ height: 200 }}> <ScrollView ref={(ref) => { this.childScrollView = ref; }} onScroll={this.handleChildScroll} > {/* 子ScrollView的内容 */} </ScrollView> </View> {/* 父ScrollView的其他内容 */} </ScrollView> ); } } export default ParentScrollView; ``` 在上面的代码中,首先在父ScrollView的state中记录了一个isChildScrolling和childScrollTop变量,分别表示子ScrollView是否正在动,以及子ScrollView的当前scrollTop值。然后在父ScrollView的onTouchStart事件中,根据手指位置是否在子ScrollView的范围内,来判断是否将事件交给子ScrollView处理。在onTouchMove事件中,如果子ScrollView正在动,则通过scrollTo方法来动子ScrollView。在onTouchEnd事件中,清除掉记录的变量信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值