react native自定义滚动吸顶位置

自定义滚动吸顶位置

在这里插入图片描述
在这里插入图片描述

  1. 父组件中主要的工作使用的是动画Animated,对Animated.ScrollView组件的onScroll监听滚动位置,使用Animated.event 将偏移量保存
    import React, {useRef} from 'react';
    import {
      Text,
      View,
      ScrollView,
      Animated,
    } from 'react-native';
    // 这是我自定义的顶部图片
    import EveryDayRecommend from '@/view/DailyRecommendation/components/EveryDayRecommend/EveryDayRecommend';
    // 这个组件使用的是吸顶的组件,抽出来方便其他页面组件使用
    import StickyHeader from '@/view/DailyRecommendation/components/StickyHeader/StickyHeader';
    const DefaultRecommend = () => {
      // 初始化动画
      let scrollY = useRef(new Animated.Value(0)).current;
      // 指定到定位哪个位置停止滚动
      let stickyTopY = useRef(200).current;
    
      return (
        <View>
          <Animated.ScrollView
          // 通过OnScroll结合 Animated.event保存顶部偏移量
            onScroll={
              Animated.event(
                [
                  {
                    nativeEvent: {
                        contentOffset: {
                        	y:scrollY
                        }
                    }, // 滑动距离
                  },
                ],
                {useNativeDriver: true},
              ) // 使用原生动画驱动
            }>
            {/* 自定义吸顶组件 */}
            <StickyHeader
              stickyTopY={stickyTopY} // 头部高度,也就是吸顶位置
              stickyScrollY={scrollY} // 把滑动距离传入
            >
              <EveryDayRecommend
                source={require('@/assets/image/defaultRecommendGif.gif')}
                descBottom="默认的推荐风格"
              />
              <Text>全部播放</Text>
            </StickyHeader>
            <ScrollView>
              <View>
                {[...Array.from({length: 100}).keys()].map(item => {
                  return <Text key={item}>{item}</Text>;
                })}
              </View>
            </ScrollView>
          </Animated.ScrollView>
        </View>
      );
    };
    
    export default DefaultRecommend;
    
    
  2. 子组件StickyHeader 中接受了父组件传递的,
    1. stickyTopY = null 吸顶位置
    2. stickyScrollY 偏移量
    3. children 传递内容
    4. style 样式
    5. 在组件中使用了 Animated.View 属性onLayout 初始化会返回当前元素的属性,这里使用的情况是防止未传递吸顶高度,所以默认将其偏移量量作为吸顶高度
    import React from 'react';
    import {StyleSheet, Animated} from 'react-native';
    import {useRef} from 'react';
    
    const StickyHeader = ({
      stickyTopY = null,
      stickyScrollY,
      children,
      style,
    }) => {
      let stickyLayoutY = useRef(0).current;
      // 判断是否滚动是否存在吸顶高度,如果不存在将当前元素到高度设置为吸顶高度
      let y = stickyHeaderY !== null ? stickyTopY : stickyLayoutY;
    
      // 初始化高度,没有传递吸顶位置时使用
      const onLayout = event => {
        stickyLayoutY = event.nativeEvent.layout.y;
      };
    
      return (
        <Animated.View
          onLayout={onLayout} // 元素初始化时会返回当前元素的属性
          style={[
            style,
            styles.con,
            {
              // interpolate函数用于创建一个动画,
              // 将输入范围映射到输出范围 stickyScrollY是一个Animated.Value,正在被插值以创建一个新的Animated.Value。
              // inputRange数组指定了stickyScrollY值可以取的范围,outputRange数组指定了新的Animated.Value将取的值的范围。
              //  outputRange数组是[0, 0, 0, 1]。这意味着当stickyScrollY小于-1时,新的Animated.Value将为0。
              //  当stickyScrollY在-1和0之间时,新的Animated.Value将为0。当stickyScrollY在y和y + 1之间时,
              //  新的Animated.Value将为0。当stickyScrollY大于y + 1时,新的Animated.Value将为1。
              transform: [
                {
                  translateY: stickyScrollY.interpolate({
                    inputRange: [-1, 0, y, y + 1],
                    outputRange: [0, 0, 0, 1],
                  }),
                },
              ],
            },
          ]}>
          {children}
        </Animated.View>
      );
    };
    
    export default React.memo(StickyHeader);
    
    const styles = StyleSheet.create({
      con: {
        zIndex: 10,
      },
    });
    
    
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值