RN ScroolView 从物理学角度理解触摸滚动事件

前言

本文旨在介绍React Native ScrollView官方文档中未提及的滚动事件API,着重介绍如何从物理学角度理解onMomentumScrollBeginonMomentumScrollEnd函数。

至于官方文档中为何不提及这些API,个人理解是目前文档也在不断更新,文档还未完善。亦或是我打开的姿势不对?希望知道的朋友能科普下,解锁新的姿势。

ScrollView简介

一个包装了平台的ScrollView(滚动视图)的组件,同时还集成了触摸锁定的“响应者”系统。
记住ScrollView必须有一个确定的高度才能正常工作,因为它实际上所做的就是将一系列不确定高度的子组件装进一个确定高度的容器(通过滚动操作)。要给一个ScrollView确定一个高度的话,要么直接给它设置高度(不建议),要么确定所有的父容器都已经绑定了高度。在视图栈的任意一个位置忘记使用{flex:1}都会导致错误,你可以使用元素查看器来查找问题的原因。
ScrollView内部的其他响应者尚无法阻止ScrollView本身成为响应者。

官方文档介绍的API

官方文档中提及了三个与事件回调相关的API,如下所示:


图-1

官方文档未介绍的API

此处只列出ScrollView特有的事件回调API,关于“响应者系统”的回调API一下就不列出了。

API Description
onTouchStart 按下屏幕时触发
onTouchMove 移动时触发,实际上按住不动也会触发
onTouchEnd 手指离开屏幕时触发,Android测试当有拖曳行为时会调用onScrollEndDrag来代替之;当无拖曳行为时,手指离开就会触发
onScrollBeginDrag 开始拖动时触发,滚动开始的标志
onScroll 滚动过程中调用,一帧最多调用一次
onScrollEndDrag 拖曳结束时调用,顶替onTouchEnd
onMomentumScrollBegin 手指离开屏幕时调用(瞬时冲量滑动的开始)
onMomentumScrollEnd 滚动结束时调用(瞬时冲量滑动的结束)

起初很不理解最后俩个方法的描述,网上一查资料,解释为“一帧滚动的开始结束”,“帧滚动”是什么鬼?一脸懵逼,我拖曳的时候画面不是一直在滚动吗?意思会调用好几次?百度、google无果,只能一脸懵逼的自己写Demo验证了。
Momentum一词指物理学中动量,再解释之前,我们先回顾下高中所学的物理知识。
动量定理

图-2

瞬时冲量:极短时间内力F产生的冲量,简单点就理解为物体的速度会突变,举个例子就是你给一个静止的物体,施加一个瞬时冲量,那瞬间,物体的速度会从0突变到另外一个值,而位移未曾改变。

结论:这组函数是用于响应你手指在离开屏幕那一刹那(极短时间),对物体在滑动反方向上所施加力的作用效果,这时会产生一个瞬时冲量,至使物体速度突变,之后的滑动过程就是一个减速运动至速度为零(ScrollView内部会模拟产生一个摩擦力)。
这就是为什么在ScrollView的实际操作当中,当我们用力滑动一小截,ScrollView就会连翻好几页的原因。
简而言之
onMomentumScrollBegin会在你手指离开屏幕时调用,不过在此之前会先调用onScrollDragEnd,onMomentumScrollEnd会在滑动结束时调用。

Demo测试验证

测试情景一:
手指按住,不移动(持续1-2s),然后离开屏幕,测试结果如下如所示:

图-3

可见onTouchMove在测试期间共调用了35次,并不是如网上所言在移动时候调用,而是在onTouchStart后就会调用,手指离开屏幕就会调用onTouchEnd结束事件响应。
注意,onTouchMove传进来的nativeEvent并没有contentOffset属性(图片相对ScrollView容器的滑动偏移量)如图-4所示,这也从另外一个方面说明它不是在移动的时候调用。
图-4

测试情景二:
手指按住屏幕,慢慢的拖动一段距离,再最后要离开屏幕时,手指往滑动反方向用力,测试结果如下所示,图中数字表示滑动方向的偏移量:
图-5

上面说到onTouchMove并不是在滑动时调用,那么滑动开始回调API是谁呢?聪明的你肯定想到了,没错就是onScrollBeginDrag,代表滑动的开始。该函数接收的nativeEvent才包含了contentOffset属性,如图-5所示。

图-6

onScroll就是在滑动的过程中会调用。
重点来了
在你手指离开屏幕时,会先调用onScrollEndDrag,表示拖动结束,接下来,就如上面我们分析的一样,根据你手指离开屏幕时所施加的力,计算这个瞬时冲量该让图片滑动多少距离。依次调用onMomentumScrollBegin,onScroll,onMomentumScrollEnd。
测试代码就不上了,太长了,写起来也很简单。

最后,由于本人水平有限,第一次写文章,文中难免有不妥之处,还请多多体谅。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,352评论 4 61
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,907评论 25 709
  • 2014的 O2O 想要革传统行业的命,几乎所有的行业都有 O2O 创业公司的身影,这股热潮也让我心生萌芽,但当我...
    秋橙阅读 3,483评论 0 2
  • 问题描述 笨方法:O(n2) 分治O(nlogn) 1)将数组分成两半,分别求出左半边的逆序数和右半边的序数2)再...
    Co_zy阅读 4,417评论 0 1

友情链接更多精彩内容