反应原生滑动天花板效果的实现过程
前言
最近公司发展方向偏向移动端,所以转做RN(react-native),体验还不错。目前对主页中间吸顶的效果有需求。虽然文风很久没写了,但这种常见的文风应该也就那么简单,不可能翻车。网上搜索几个方案都改不了。最后把打包好的库复制到github上实现,现在记录翻车过程。
需求效应
翻转过程
第一个方案失败了
一开始的想法是这样的。流行的想法是,我们需要监控页面的滚动状态。当页面滚动到要吸附顶部元素的位置时,我们将其设置为固定位置。遗憾的是,RN只为position属性提供了绝对和相对两种布局模式,既没有固定也没有api:sticky,目前还在实验中。笨拙的
第二个方案失败了
然而,没有恐慌。互联网上还有第二个方案。地图上的第二个和第三个地方作为ScrollView,然后ScrollView滑动收听距离,将第一块的marginTop设置为负值,但是第一部分不能滑动,不符合要求。通过,
第三个方案彻底失败了
第三个方案是在网上找到的,就是把一、二、三部分作为ScrollView。
位置的第一部分设置为绝对,其余部分未设置,默认为相对
第二部分(天花板部分)的余量被设置为第一部分的高度状态,
添加滑动onScroll事件=“滑动距离y等于第二部分marginTop的状态,但是当滑动超过第一部分的高度时,将第二部分(吸顶部分)的位置设置为绝对,将其marginTop设置为0,看起来不错。其实用ios模拟器运行的时候,你会无语,效果很棒。当你滑动手指时,你可以直接画它来隐藏大部分,而不吸顶部,当它松开时,它会突然吸顶部。
见下文
在ios系统中,当手指在屏幕上滚动时,onScroll总是被触发。如果其中有setstate方法,它将继续执行并计算状态,但是改变react状态是异步的。只要手指不离开屏幕,改变的状态就不能生效(触发界面渲染)
实施方案
我终于意识到,由于ios机制的原因,react的状态机制不能满足需求,必须有办法在RN中使用原生渲染。于是github找到了现成的代码实现,然后依次进行研究。每个有丰富RN经验的人也可以直接看底层代码。
RN的动画师
RN的Animator动画库旨在解决动画问题。由于js桥接过程,动画通常不能很好地显示。最好将动画数据和更改方法一次性发送给原生,由原生来处理。这是Animator库的核心功能。
我记得RN的动画一直被吐槽,但是现在效果还挺好的,可能跟这几年手机硬件越来越完善有关。
简单用法
由于这四个组件封装在Animator中,默认情况下可以导出animator.view/、animator.text/、animator.image/、Animator . scroll view/。
我想在这些组件中做一些动画处理,数据也是反应状态,但是分配应该给动画。值,如下所示
这个。状态={ scrolly:new新动画。value (0)}虽然这里使用了原生状态,但动画处理后的渲染机制完全不同
简单原则
动画师包装的组件将遍历传入的道具和它们自己的状态,以找出是否有动画的实例。值,并绑定到相应的本机操作中。
当道具及其自身状态发生变化时,动画。值值被一个一个转换成普通值,然后交给原生进行渲染。但是,值得注意的是,这里不会有react render,也不会有domdiff,这是一个特殊的处理。类似于动画时。值改变时,shouldupdatecomponent每次返回false(毫秒级渲染反应性能无法支持),shouldupdatecomponent函数判断为动画。值,然后将数据更改发送到本机组件
完整的介绍请到中国官网动画师库进行介绍
实现理念
现在已经使用了Animator组件,渲染问题已经解决。下面的想法是动态设置天花板组件的translateY属性。style : { transform :[{ translatey : translatey }]}
向下滑动的时候,不管它向上滑动,但是当头部没有完全隐藏的时候,不管它向上滑动,头部就完全没有了。这时,如果它向上滑动一点,那么他的平移应该等于向上划水的总距离——头部的高度。它向上滑得越多,向下推天花板组件的力就越大,这样天花板组件就牢牢地固定在顶部。以下是通过插值实现的
const translateY=scrolly . interpolate({ inputrange :[-1,0,header heit,header heit 1],outputRange: [0,0,0,1],});插值有点难懂,需要一点基础。这里要细说一下,这篇文章太长了。官网介绍了一下。
如果你仍然不明白,你可以在网上寻找这方面的信息
实现源代码
实现了图中天花板功能第二部分的核心代码
从“反应”中导入*作为反应;从“react-native”导入{样式表,动画};/* * *导出默认类StickyHeader扩展了React。组件{静态默认道具={ stickyheader :-1,stickyScrollY:新动画。Value(0) }构造函数(道具){ super(道具);this.state={ stickyLayoutY:0 };}//防止header _ onlayout=(event)={ this . setstate({ stickylyout : event . nativeevent . layout . y,})的兼容代码;} render(){ const { stickyReady,stickyScrollY,children,style }=this . props const { stickyLayouty }=this . state让y=stickyHeaderY!=-1 ?stickyHeaderY : stickyLayoutYconst translateY=stickyscrolly . interpolate({ inputrange :[-1,0,y,y ^ 1],outputRange: [0,0,0,1],});返回(动画。查看onLayout={ this。_onLayout } style={ [ style,styles.container,{ transform :[{ translateY }]}]} { children }/Animated。view)} } const style=style . create({ container : { zindex : 100 },});页面上的实际用法如下
//声明statethis。state={ scrolly:nnewanimated。页面构造函数中的值(0,headheight :-1 );动画。scroll view style={ { flex : 1 } } onScroll={动画. event([{ nativeevevent : { contentoffset : { y : this . state . scrolly } }//记录滑动距离}],{ usenativedriver : true })//使用原生动画驱动} scroll event time={ 1 } view onlayout={(e)={ let { height }=e . native event . layout;this . setstate({ head height : height });//给head height赋值} }//将组件的第一部分放入/view粘性header粘性headery={ this。state . head height }//将头部高度传递到粘性卷轴={this。state . scroll }//传入滑动距离//放入组件的第二部分/StickyHeader //这是列表组件的第三部分平面列表数据={this。state.datasource}呈现项={({item})=此。_创建列表项(item)}//动画。滚动视图结束
具体的代码就是这样实现的,这是一个完美的方案,特别是照顾到了性能。基于这个包,您可以实现更复杂的需求。原理大概就是这个原理。在前端动画领域,你才刚刚起步。如果你有任何问题,请直接指出。
另外,这是我要找的组件github的代码地址:https://github.com/jiasongs/react-native-stickyheader,原地址附后,如果项目使用建议给人一颗星
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。谢谢你的支持。
版权声明:反应原生滑动天花板效果的实现过程是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。