前端知识 | React Native手势响应浅析

目前手机市场上,全面屏时代已经势不可挡,为了增大屏幕,一个个物理按键已渐渐消失在手机上。那么,手势将成为在移动应用开发中一个重要的组成部分,移动设备上手势识别要比 web 端复杂得多,往往用户的一个手势,我们在 APP 上要通过好几个阶段去判断用户的真实意图是什么,在 ReactNative (以下简称 RN)中针对手势处理也提供了从最基本的点击手势到复杂的滑动等一系列解决方案,让我们一起去看看。

RN基本触控组件

RN 的组件除了 Text,其他组件默认是不支持点击事件的,也不能成为一个触摸事件的响应者。RN 提供了几个比较直接的处理响应事件的组件,基本上能满足大部分的点击事件的处理需求。

TouchableHighlight

TouchableNativeFeedback (仅限 Android 平台)

TouchableOpacity

TouchableWithoutFeedback

这几个组件的功能和使用方法基本类似,只是就 Touch 的效果反馈上有所差异,他们有如下几个回调方法:

onPressIn:用户触摸开始的时候,也就是手指刚落在 Touch 点击区域内的时触发

onPressOut:用户触摸结束的时候,也就是手指从 Touch 点击区域内抬起的时触发

onPress:用户完成一次从 onPressIn 到 onPressOut 的过程,且时间很短,即一次快速点击操作时触发

onLongPress:用户触发 onPressIn 且手指一段时间内没有抬起时触发

这里以 TouchableHighlight 为例,贴一个 Touch 的基本用法:

RN 中提供的 Touch 组件的使用非常简单,可以参考官方文档,这里就不做详细的介绍了,我们主要来说下用户的触摸事件处理。

gesture responder system

在 RN 中,响应手势的基本单位是 responder,具体点说就是最常见的 View 组件。任何的 View 组件都可以成为一个手势的响应者。其实要把一个普通的 View 组件开发成为一个能响应手势操作的 responder 很简单,话不多说,我们举栗子!

乍一看,WillMount 里面的这几个方法名字又长又奇怪,但是等你了解了 RN 手势响应的流程了之后,记忆这几个方法就非常简单了。在我们探索这几个方法之前,我们首先要记住一个重要的点:

一个 RN 应用中只能存在一个 responder!

一次正常的手势操作的流程如下所示:

是否响应 Touch 或者 move 手势->grant(被激活) ->move->release (结束事件)

与流程相对应的方法是:

onStartShouldSetResponder(event) => true:在用户开始进行触摸操作时(手指刚刚接触屏幕的瞬间),询问是否申请成为触摸事件的响应者,返回 true 为需要成为响应者。

onMoveShouldSetResponder(event) => true:如果绑定的View不是响应者,那么会在用户的触摸点开始移动的时候再次询问是否申请成为触摸时间的响应者,返回true

为需要成为响应者。

假设组件通过上面的方法返回了 true,表示发出了申请需要成为响应者,但是我们前面说过,一个 RN 应用中只能有一个 responder,那么接下来就需要协调所有组件的请求,看看这个响应者的位置给谁。

onResponderGrant:(event) => {}:View 申请成功,并成为了响应者。一般情况下,这时开始,组件进入了激活状态,并进行一些事件处理或者手势识别的初始化。

onResponderReject: (event) =>{}:View 申请失败了,这就意味着有其他的组件正在成为或者已经成为了响应者,并且他不愿意交出这个权利。所以你被拒绝了~

如果你成为了响应者,那么会收到后续的事件输入并由你来决定他的行为动作:

onResponderMove: (event) => 表示触摸手指的移动事件,这个回调在一次完成的手势动作中可能会非常频繁的调用,所以这个回调函数里面的内容需要尽量简单

onResponderRelease: (event) => 表示触摸完成,相当于前面讲的 Touch 里面的 onPressOut 方法,表示用户已经完成了本次的触摸操作,同时会释放响应者这个权利。

在你成为响应者期间,其他组件也有可能会申请成为响应者,那么此时RN会通过回调来询问当前的响应者是否放权给其他申请者。回调如下:

onResponderTerminationRequest: (event) => true:如果我们返回的是 true,那就代表当前响应者同意放权,让其他的组件来当响应者,自己回归平淡的生活,同时也会回调一个函数,通知组件事件响应处理被终止了:

onResponderTerminate: (event) => {}:这个回调也会发生在系统直接终止组件的触摸事件处理中,比如用户在进行触摸操作的时候,来电话了,或者意外闪退了。

相信大家都发现了,所有的方法都有一个 event 参数,里面包含了一个触摸事件数据 nativeEvent,nativeEvent 具体结构如下图:

chanedTouches:event 数组,从上次回调上报的触摸事件,到这次上报之间的所有事件数组。因为在用户触摸过程中会产生很多事件,有时候可能还没来得及上报,系统就用这种方式批量上报

identifier:触摸的 ID,这个 ID 存在周期为从触摸开始到释放为止,主要是用来区别在多点触控的情况下,区分是哪个手指的触摸事件。

locationX 和 locationY:触摸点相对于组件的位置

pageX 和 pageY:触摸点相对于屏幕的位置

target:接收当前触摸事件的组件 ID

timestamp:当前触摸的事件的时间戳,可以用来进行滑动的相关计算(速度,停留时长)

touches:event 数组,多点触摸的时候,包含当前所有触摸点的事件

冒泡机制和事件捕获

先前我们都是针对单一组件来说的,但是在实际开发过程中,我们往往会遇到很多嵌套之类的组件,那如果在我们多重嵌套的组件中,每层组件绑定了一个手势响应且 onStartShouldSetResponder 或者 onMoveShouldSetResponder 回调都返回了 true 来申请成为响应者的话,又会怎么样呢?我们举个栗子来看看:

在这个大栗子中,我们嵌套了两层组件,使得组件布局如图:

在RN中,默认情况下会遵循冒泡机制,也就是嵌套最深的组件最先开始响应,那么我们栗子中的三层组件的 onStartShouldSetResponder 或者 onMoveShouldSetResponder 全部都返回 true 的情况下,那么 C 组件会优先成为事件响应者。但在我们的实际开发中,可能你需要的是父组件去处理触控事件,而禁止子组件响应,那肿么办?。RN 给我们提供了一个事件捕获机制,也就是在触摸事件通过冒泡机制往下传递的时候,先询问上层有申请的组件是否捕获该事件,不给子组件传递事件,即上面的栗子中,正常情况下通过冒泡机制,我们的触控事件会 A->B->C 这样传递到 C 去响应事件,当 A 传递到 B 时,会询问 A 是否捕获这个触控事件并且不再向下传递给 B 和 C,如果 A确认捕获,那么 A 即成为这个事件的响应者。具体的回调是:

onStartShouldSetResponderCapture: () => true :在触摸事件开始的时候,RN 容器的组件就会收到这么一个回调函数,询问是否捕获事件成为响应者,如果返回true,表示确认捕获事件

onMoveShouldSetResponderCapture: () =>true :在触摸事件开始移动的时候,再次询问是否捕获事件成为响应者,如果返回 true,表示确认捕获事件

PanResponder

除了 gesture responder system 之外,RN 还抽象出了一套 PanResponder 方法,这套方法的好处在于,使用起来更方便,在不改变原有的逻辑和流程的前提下,提供了更多的参数,包含了手势进行过程中更多的信息,让我们更好的去理解和处理用户的手势意图,话不多说,直接上栗子。

在上面的栗子中,我们实现了在一个白色有边框的事件响应者开始响应事件而变成绿色,然后实现拖拽效果并且在拖拽过程中变成红色,最后在释放手指又变回白色的这么一个过程。

大体上和 gesture responder system 一样,我们要注意的就是几个方法的写法加上了 Pan,并且几个回调函数多了一个 gesture 参数,他具体长这样的:

dx 和 dy:从触摸操作开始到现在的累积横向/纵向路程

moveX 和 moveY:最近一次移动时的屏幕横/纵坐标

numberActiveTouches:当前在屏幕上的有效触摸点的数量

stated:和之前一样,用来识别手指的ID

vx 和 vy:当前横向/纵向移动的速度

x0 和 y0:当触摸操作开始时组件相对于屏幕的横/纵坐标

总结

以上是我对 RN 的一些基础学习和理解,只举了一些简单的栗子,要在项目里实现一些更为复杂的手势操作,还需要进一步的摸索研究。另外需要注意的是,上述的回调函数都是在 JS 线程中进行的,可能会有些许延迟。

【海说软件接受各种技术咨询及开发业务】

-END-

原文地址:http://blog.51cto.com/13476205/2062503

时间: 2024-11-05 21:45:53

前端知识 | React Native手势响应浅析的相关文章

前端知识 | React Native Animated动画浅谈

在移动开发中,动画能有效的提高用户体验.在 React Native 中,也有相应的 API 供我们做动画.这里着重说一下 Animated 动画库,它可以让我们非常简便的去实现各式各样的动画和交互方式,而且具备很高的性能.Animated 目前只封装了四个可以动画化的组件:View.Text.Image.ScrollView,不过你也可以用 Animated.createAnimatedComponent() 来封装你自己的组件. 话不多说,我们来举个栗子: 步骤拆解 1.创建 Animate

[深入剖析React Native]手势响应讲解

手势识别在移动设备上比在网络上要复杂得多.当应用程序确定用户的意图时,一个触摸可能要经历几个阶段. 例如,应用程序需要确定触摸是否是滚动,滑动部件还是轻击,地图上的缩放.这甚至可以在触摸期间发生改变,也可以有多个同时触摸. 要想使组件在没有任何额外的关于它们的父组件或子组件的认知的情况下处理这些触摸交互,需要触摸应答系统.这个系统在ResponderEventPlugin.js 中实现了,其中包含更多细节和文档. 最佳实践 用户在 web app与native app的可用性上可以感觉到巨大的差

React Native 调研报告

Facebook三月份开源了React Native iOS平台的框架,让移动开发人员和web开发者都各自兴奋了一把:native的移动开发者想的比较多的估计是Facebook的那句:"learn once, write everywhere",而web开发者兴奋的估计是,不需要学习iOS那陌生的OC或者swift语言,用自己熟悉的javascript语言就可以开发原生的移动APP了.那么新推出的react native 能否承载的了两大阵营的开发者的期待了.本人及同事对react n

React Native基础与入门(二)--初识React Native

React Native组件 React Native是用React Native框架来组建Android和IOS App的技术,那么React Native组件就是React组件.React组件让你将UI分割成独立的.可重用的一些碎片或部分,这些部分都是相互独立的. 创建组件的三种方式 1.ES6创建组件的方式 export default class HelloComponent extends Component { render() { return <Text style={{font

初识React Native

前言 React Native是最近非常火的一个话题,想要学习如何使用它,首先就要知道它是什么. 好像面对一个新手全面介绍它的文章还不多,我就归纳一下所有的资料和刚入门的小伙伴一起来认识它~ 将从以下几个方面来介绍它: 1.React Native的定义 2.React Native的优缺点 2.学习React Native需要掌握的知识 React Native的定义 一句话就是:一款专门用于App的JS框架. React Native 结合了 Web App和 Native App的优势,使

React Native 五:手势

一.Touchable手势 1.React Native提供了4个组件来做这个事情,具体如下: TouchableHighlight:高亮触摸,用户点击时,会产生高亮效果: TouchableNativeFeedback: TouchableOpacity:透明触摸,用户点击时,点击的组件不会出现任何视觉变化: TouchableWithoutFeedback:无反馈触摸,用户点击时,点击的组件不会有任何视觉变化: 2.这4个组件,我们可以应用某个部分绑定上Touch事件,并支持一下方法: on

React Native 入门基础知识总结

中秋在家闲得无事,想着做点啥,后来想想,为啥不学学 react native.在学习 React Native 时, 需要对前端(HTML,CSS,JavaScript)知识有所了解.对于JS,可以看看阮一峰老师的<ECMAScript 6 入门>这篇文章.里面涉及很多 ES6 的新特性.我之前也是看了阮老师的文章做了一些学习笔记 ES6 学习笔记. 1.环境搭建 环境搭建中文教程,点击跳转RN中文社区 :http://reactnative.cn/docs/0.40/getting-star

React Native Android Gradle 编译流程浅析

[工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 前面已经发车了一篇<React Native Android 从学车到补胎和成功发车经历>,接着就该好好琢磨一下 React Native 周边了,没看第一篇的可以先去看看:这里我们先从 React Native 的 Android 编译来简单揭晓一下 React Native 在集成的过程中到底干了哪些不可告人的坏事:由于我们项目准备以 Gradle 形式接入

React Native知识

http://www.cnblogs.com/wujy/tag/React%20Native/ React Native知识12-与原生交互 React Native知识11-Props(属性)与State(状态) React Native学习笔记之2 React Native知识10-ListView组件 React Native知识9-ScrollView组件 React Native知识8-WebView组件 React Native知识7-TabBarIOS组件 React Native