react-native 列表吸顶效果&滑动渐变动画&轮播渐变动画

react-native 实现列表吸顶效果

实现列表吸顶效果,这里是使用RN自带组件SectionList自带的特性。
在这里插入图片描述

RN 结合 MobX之后的生命周期使用

在说明SectionList实现列表吸顶功能之前,先爆料承接上一篇文章 在使用MobX时候,生命周期问题。在方法componentDidUpdate()中请求后台的方法莫名无故的一直请求数据,页面卡顿!!就拿上面的Gif效果图来说。因为每进行一次页面的渲染就会调用react的生命周期 componentWillUpdate() 和 componentDidUpdate() 如果我们误把页面数据的请求方法放到了方法componentDidUpdate()中,然后你就会发现,数据请求方法一直不听的在像后台请求数据。页面略显卡顿,因为起初进入到这个生命周期中,调用请求后台数据的方法,请求到之后,会赋值让页面重新渲染,然后有回调用方法componentDidUpdate() 然后就导致了死循环的无限请求和渲染中!解决方案,是在生命周期方法componentDidMount()中处理。

SectionList 在安卓和iOS系统上的差异

`SectionList 的 方法scrollToLocation()

在这里插入图片描述
SectionList的这个方法,在使用上iOS平台达到预期效果,但是Android平台则不能!实现的效果是上图Gif图右下角悬浮的一个上箭头,点击页面回滚到顶部。 实现方式也很简单,动态计算SectionList的Header组件View的高度,回调并调用回滚方法scrollToLocation()。像这样
在这里插入图片描述中间去调节这个bug,而且成功了,我改动了下参数去掉了参数viewPosition,然后运行在安卓上成功了。但是后来不知怎么的,又不行了!目前还没有好的解决方案。

`SectionList 的 props属性stickySectionHeadersEnabled

在这里插入图片描述
SectionList在使用的时候section都会吸顶停留(像上图Gif,横向的秒杀组件),原因是iOS的系统特性,默认就可以的。但是换做在Android上则不能,直接就像FlatList一样不能实现吸顶效果。原因是在安卓平台,需要我们手动进行设置 stickySectionHeadersEnabled=true。
在这里插入图片描述

实现SectionList吸顶效果

看部分实现源码——列表主控件

<SectionList
          style={{ flex:1}}
          ref={sctionList => (this._sectionList = sctionList)}
          keyExtractor={(item, index) => "SectionList" + index}
          renderItem={this._renderSectionItem}
          stickySectionHeadersEnabled={true}
          showsVerticalScrollIndicator={false}
          ListHeaderComponent={this._renderHeader}
          onEndReachedThreshold={0.01}
          onEndReached={this._fetchMoreListData}
          onScroll={(ee) => {
            this.isShowUpward = ee.nativeEvent.contentOffset.y > 150
            // this.isShowUpward = ee.nativeEvent.contentOffset.y > 100; //是否显示返回顶部按钮
            this.flatListNum = ee.nativeEvent.contentOffset.y;
            if(this.flatListNum > 5 && this.state.colorX == true){
                this.setState({colorX:false})
            }else if(this.flatListNum <= 5 && this.state.colorX == false){
                this.setState({colorX:true})
            }
            this.bar && this.bar.onScroll(ee);
        }}
          refreshControl={
            <RefreshControl
              refreshing={this.isRefreshing}
              onRefresh={this._refreshControl}
              tintColor="#000"
              title={this.refreshTitle}
              titleColor="#666"
            />
          }
          renderSectionHeader={({ section }) => (
            <HorizontalScroll
              ref={hscroll => (this._hscroll = hscroll)}
              scrollTabs={this.state.scrollTabs}
              onPress={hindex => {
                  this.clickIndex = hindex;
                  //这里响应了用户点击抢购时间按钮,要进行请求数据
                this._fetchMoreListData(false);
              }}
            />
          )}
          sections={this.state.sectionListData}
        />

源码中,第42行 传入列表数据,数据结构是这样的。只有一条数据来实现的!
在这里插入图片描述
产生下面的效果
在这里插入图片描述
SectionLIst本身就有setction吸顶的特点,正好利用这一特点。通过实现SetctionList 的一条数据。
第8行代码实现的是这个列表的Header,
第5行代码实现了列表item单元格元素,
第31行代码实现了要吸顶的view即setcion,使用FlatList作为横向滑动。

实现TitleBar跟随滑动渐变的动画

在这里插入图片描述
请看源码片段中的第11行到21行,当向下滑动列表,SetcionList的API回调方法onScroll被调用。即this.bar && this.bar.onScroll(ee);被调用实现渐变的方法。TitleBar动画组件定义

<AnimatedBackground ref={ref => this.bar = ref} colors={this.bgColors} >
     <MyTitleBar  />
 </AnimatedBackground>

this.bar && this.bar.onScroll(ee);结合 TitleBar动画组件可知我们要进行对该操作的手势处理。在这里插入图片描述
从官方文档来看,想要实现滑动渐变,即让你滑动的距离映射到动画值。在这里的功能实现上,调用this.bar && this.bar.onScroll(ee);则可以实现。在这里插入图片描述
由此,滑动的距离 就和 this.state.color(即:color=new Animated.Value())产生了映射。然后通过插值动画来实现效果,如下代码

<Animated.View style={{
                backgroundColor:this.state.color.interpolate({
                    inputRange: [0, isIphoneX ? 88 : 64],
                    outputRange: ['#F3474600', '#F34746FF']
                })
            }}>
                {this.props.children}
 </Animated.View>

整个实现过程就是,TitleBar的背景渐变通过插值动画来实现背景的渐变通过在['#F3474600', '#F34746FF']这两种颜色值之间进行渐变变换。对应渐变滑动值=0,对应是色值#F3474600;滑动值=88或64,对应是色值#F34746FF。而在滑动值0到88之间,色值也在[’#F3474600’, ‘#F34746FF’] 两种颜色间渐变。而插值实现背景的渐变需要this.state.color[color=Animated.Value()]和滑动距离constentOffset 产生映射,即通过方法Animated.event()来实现。而控制映射的时机,则是在列表滑动,通过在回调方法onScroll中调用!

实现TitleBar跟随轮播渐变的动画

在这里插入图片描述
而实现,轮播图轮播,TitleBar跟随渐变。从实现角度看,轮播变动是水平切换滚动,滚动距离要与颜色值产生映射。实现代码在x轴:

onScrollX = (e) => {
        Animated.event([{
            nativeEvent: {
                contentOffset: {
                    x: this.state.colorx
                }
            }
        }])
    }

然后使用插值变化实现代码

<Animated.View style={{
                backgroundColor: this.state.colorx.interpolate({
                    inputRange: this.props.colors.map((_, i) => (i) * c.fitPx(710)),
                    outputRange: this.props.colors
                })
            }}>
                {this.props.children}
 </Animated.View>

代码和竖直方向滚动的渐变实现很类似,这个时候只需在轮播组件上调用方法,使水平滚动距离和颜色值产生映射的方法即可。
在这里插入图片描述
水平轮播滚动距离和颜色值产出映射,在TitleBar的背景style上进行插值器调用,Animated.View作为背景,在轮播过程中就会执行渐变动画。
完整的TitleBar渐变背景组件实现代码(这个是对双向的渐变动画控制实现)

export class AnimatedBackground extends Component {
    state = {
        color: new Animated.Value(0),
        colorx:new Animated.Value(0)
    }

    onScrollX = (e) => {
        Animated.event([{
            nativeEvent: {
                contentOffset: {
                    x: this.state.colorx
                }
            }
        }])
    }
    onScroll = Animated.event([{
        nativeEvent: {
            contentOffset: {
                y: this.state.color
            }
        }
    }])
    
    render() {
        // colorX=是否是水平滑动
        return (
            <Animated.View style={{
                backgroundColor: this.props.colorX ? this.state.colorx.interpolate({
                    inputRange: this.props.colors.map((_, i) => (i) * c.fitPx(710)),
                    outputRange: this.props.colors
                }):this.state.color.interpolate({
                    inputRange: [0, isIphoneX ? 88 : 64],
                    outputRange: ['#F3474600', '#F34746FF']
                })
            }}>
                {this.props.children}
            </Animated.View>
        )
    }
}
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值