React Native 五:手势

一、Touchable手势

1.React Native提供了4个组件来做这个事情,具体如下:

TouchableHighlight:高亮触摸,用户点击时,会产生高亮效果;

TouchableNativeFeedback:

TouchableOpacity:透明触摸,用户点击时,点击的组件不会出现任何视觉变化;

TouchableWithoutFeedback:无反馈触摸,用户点击时,点击的组件不会有任何视觉变化;

2.这4个组件,我们可以应用某个部分绑定上Touch事件,并支持一下方法:

onPress:

onPressIn:

onPressOut:

onLongPress:

3.下面我们以实例演示下,相关代码实现:

Index.android.js文件:

import React, {
  … …
  TouchableHighlight,
} from ‘react-native‘;

class AwesomeProject extends Component {
  show(text) {
    alert(text);
  }
  //手势相关事件的实现
  onPressIn(){
    this.start = Date.now()
    console.log("press in")
  }
  onPressOut(){
    console.log("press out")
  }
  onPress(text){
    console.log("press")
    alert(text);
  }
  onLonePress(){  AppRegistry,
    console.log("long press "+(Date.now()-this.start))
  }
  render() {
    return(
      <View style={styles.container}>
        //TouchableHighlight包裹绑定Touch手势的组件,并实现支持的4个事件
        <TouchableHighlight style={styles.touchable} onPressIn={this.onPressIn} onPressOut={this.onPressOut}
          onPress={this.onPress.bind(this,‘点击了吗?‘)} onLongPress={this.onLonePress}>
          <View style={styles.button}></View>
        </TouchableHighlight>
      </View>
    )
  };
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: ‘center‘,
    alignItems: ‘center‘,
    backgroundColor: ‘#F5FCFF‘,
  },
  button:{
    width: 200,
    height: 200,
    borderRadius: 100,
    backgroundColor: ‘red‘
  },
  touchable: {
    borderRadius: 100
  },
});
AppRegistry.registerComponent(‘AwesomeProject‘, () => AwesomeProject);

4.点击,我们看见具体的运行效果如下:

5.我们使用Debug模式,研究下4个手势出现的条件和顺序;

摇晃手机,选择Debug JS;

打开Chrome浏览器,在弹出的Debug页面http://localhost:8081/debugger-ui后,选择开发着工具,点击手机上的按钮就可以看见浏览器控制台的

输出内容PressIn->longPress->pressOut;

二、手势响应生命周期

1.对于大部分应用,使用以上4个Touch*组件,在配合4个Press事件就能对用户的手势进行响应。但是对于比较复杂的交互,还得使用手势响应系统;

2.响应手势的基本单位是responder,具体来说就是View组件,任何View组件都是潜在的responder;

3.一个普通的View组件成为能响应手势操作的responder,只要设置几个手响应生命周期的方法即可,具体如下:

View.props.onStartShouldSetResponder:用户开始触摸屏幕的时候,是否愿意成为响应者;

View.props.onMoveShouldSetResponder:在每一个触摸点开始移动的时候,再询问一次是否响应触摸交互;

View.props.onResponderGrant:要开始响应触摸事件了;

View.props.onResponderReject:响应者现在另有其人,而且暂时不会放权,另作安排;

View.props.onResponderMove:用户正在屏幕上移动手指;

View.props.onResponderRelease:触摸操作结束收触发;

View.props.onResponderTerminationRequest:有其它组件请求接替响应者,当前View是否放权;

View.props.onResponderTerminate:响应权已经交出;

4.一个React Native应用中同时之能存在一个responder,具体响应步骤如下:

用户通过触摸或者滑动来“激活”某个responder,View.props.onStartShouldSetResponder以及View.props.onMoveShouldSetResponder这两个方法处理,如果返回true,则这个View能够响应触摸或者滑动手势被激活;

如果组件被激活,View.props.onResponderGrant方法被调用,一般这个时候去改变组建的底色或者透明度,表示组件已经被激活;

接下来,用户开始滑动手指,此时View.props.onResponderMove方法被调用;

当用户的手指离开屏幕之后,View.props.onResponderRelease方法被调用,组件恢复被触摸之前样式,例如底色和透明度恢复之前的样式,完成一次手势操作;

正常流程:响应touch或者move手势 -> grant(被激活) -> move -> release(结束事件);

5.下面我们以实例演示下,相关代码如下:

index.android.js文件

import React, {
   … …
} from ‘react-native‘;

var AwesomeProject = React.createClass({
  getInitialState(){
    return {
      bg: ‘white‘
    };
  },

  componentWillMount(){
    this._gestureHandlers = {
      onStartShouldSetResponder: () => true,
      onMoveShouldSetResponder: ()=> true,
      onResponderGrant: ()=>{
        this.setState({bg: ‘red‘})
      },
      onResponderMove: ()=>{
        console.log(123)
      },
      onResponderRelease: ()=>{
        this.setState({bg: ‘white‘})
      }
    }
  },

  render() {
    return(
      <View style={styles.container}>
        <View {...this._gestureHandlers} style={[styles.rect, {backgroundColor:this.state.bg}]}></View>
      </View>
    );
  }
});
var styles = StyleSheet.create({
     … …
});
AppRegistry.registerComponent(‘AwesomeProject‘, () => AwesomeProject);

6.运行效果如下,onClick为未点击,Click为点击,后面为控制台输出log:

注意:如果运行Demode的时候错误提示如下图:

使用var AwesomeProject = React.createClass();的方式创建组件;

三、手势事件传递

1.onStartShouldSetResponder于onMoveShouldSetResponder是以冒泡的形式调用的,即嵌套最深的节点最先调用;

2.意味着多个View同时在ShouldSetResponder中返回true时,最底层的View将优先”夺权“;

3.但是有些时候,某个父View会希望先能成为响应者,我们可以利用”捕获期“来解决。响应系统从最底层的组件开始冒泡前,会首先执行一个”捕获期“,在此期间会触发on*ShouldSetResponderCapture系列事件。因此,如果某个父View想要在触摸开始时阻止组件成为响应者,那就应该处理onStartShouldSetResponderCapture事件冰返回true值;

View.props.onStartShouldSetResponderCapture:(evt)=>true;

View.props.onMoveShouldSetReponderCapture(evt)=>ture;

4.下面我们将以实例演示一下,实现代码如下:

Index.android.js文件:

import React, {
     ... ...
} from ‘react-native‘;

var AwesomeProject = React.createClass({
  getInitialState(){
    return {
      bg: ‘white‘,
      bg2: ‘white‘
    }
  },
  componentWillMount(){
    this._gestureHandlers = {
      //外部正方形在“捕获期”阻止底层时间成为响应者
      onStartShouldSetResponderCapture: () => true,
      onMoveShouldSetResponderCapture: ()=> true,
      onResponderGrant: ()=>{this.setState({bg: ‘red‘})},
      onResponderMove: ()=>{console.log(123)},
      onResponderRelease: ()=>{this.setState({bg: ‘white‘})},
    }
    this._gestureHandlers2 = {
      //内部正方形在即时实现了on*ShouldSetResponder也无法成为响应者
      onStartShouldSetResponder: () => true,
      onMoveShouldSetResponder: ()=> true,
      onResponderGrant: ()=>{this.setState({bg2: ‘green‘})},
      onResponderMove: ()=>{console.log(123)},
      onResponderRelease: ()=>{this.setState({bg2: ‘white‘})}
    }
  },
  render: function() {
    return (
      <View style={styles.container}>
        <View {...this._gestureHandlers} style={[styles.rect,{"backgroundColor": this.state.bg}]}>
          <View {...this._gestureHandlers2} style={[styles.rect2,{"backgroundColor": this.state.bg2}]}>
          </View>
        </View>
      </View>
    );
  }
});
var styles = StyleSheet.create({
  ... ...
});
AppRegistry.registerComponent(‘AwesomeProject‘, () => AwesomeProject);

5.运行效果如下图,点击内部正方形,外部正方形相应事件:

四、evt参数

1.和Web开发中的事件参数类似,以上的每个方法都有一个evt参数,在事件发生的过程中,这个evt参数的nativeEvent属性的各个指能表示手势的状态:

nativeEventchangedTouches:在上一次事件之后,所有发生变化的触摸事件的数组集合(即上一次事件后,所有移动过的触摸点)

identifier:触摸点的ID

locationX:触摸点相对于父元素的横坐标

locationY:触摸点相对于父元素的纵坐标

pageX:触摸点相对于根元素的横坐标

pageY:触摸点相对于根元素的纵坐标

target:触摸点所在的元素ID

timestamp:触摸事件的时间戳,可用于移动速度的计算

touches:当前屏幕上的所有触摸点的集合

五、PanResponder

1.除了手势相应系统之外,React Native还抽象出一套PanResponder方法,它的抽象成程度更高,使用起来更为方便;

2.使用PanResponder的时候,相应手势的逻辑和流程都不变,只需要根据文档对几个方法名称参数修改即可:

第一个参数evt;

第二个gestureState,包含手势进行过程中更多信息,比较常见如下:

dx/dy:手势进行到现在的横向/纵向相对位移;

vx/vy:此刻的横向/纵向速度;

numberActiveTouches:reponder上的触摸的个数;

3.下面我们就使用PanResponder实现拖拽效果,代码实现如下:

index.android.js文件:

import React, {
  ... ...
  PanResponder,
} from ‘react-native‘;

var AwesomeProject = React.createClass({
  getInitialState(){
    return {
      bg: ‘white‘,
      top: 0,
      left: 0
    }
  },
  componentWillMount(){
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onMoveShouldSetPanResponder: ()=> true,
      onPanResponderGrant: ()=>{
        //滑动开始时,获取矩形的左上坐标,并设置背景为红色
        this._top = this.state.top
        this._left = this.state.left
        this.setState({bg: ‘red‘})
      },
      onPanResponderMove: (evt,gs)=>{
        console.log(gs.dx+‘ ‘+gs.dy)
        //随着手势滑动,相应的改变矩形的位置
        this.setState({
          top: this._top+gs.dy,
          left: this._left+gs.dx
        })
      },
      onPanResponderRelease: (evt,gs)=>{
        //活动结束后,还原背景为白色
        this.setState({
          bg: ‘white‘,
          top: this._top+gs.dy,
          left: this._left+gs.dx
        })}
    })
  },
  render: function() {
    return (
      <View style={styles.container}>
        //设置手势事件处理对象
        <View{...this._panResponder.panHandlers} style={[styles.rect,{
            "backgroundColor": this.state.bg,
            "top": this.state.top,
            "left": this.state.left}]}>
        </View>
      </View>
    );
  }
});
var styles = StyleSheet.create({
  container: {
    flex: 1,
    //开始的矩形位于中间,下图拖动到下部区域
    justifyContent: ‘center‘,
    alignItems: ‘center‘,
    backgroundColor: ‘#F5FCFF‘,
  },
  rect: {
    ... ...
  }
});
AppRegistry.registerComponent(‘AwesomeProject‘, () => AwesomeProject);

4.运行演示如下,由于只能上传图片,无法演示动画,样式中矩形位于中间,图中拖动至下方:

时间: 2024-11-07 08:56:16

React Native 五:手势的相关文章

React Native探索(五)使用fetch进行网络请求

前言 React Native可以使用多种方式来进行网络请求,比如fetch.XMLHttpRequest以及基于它们封装的框架,fetch可以说是替代XMLHttpRequest的产物,这一节我们就来学习fetch的基本用法. 1.get请求 fetch API是基于 Promise 设计的,因此了解Promise也是有必要的,推荐阅读MDN Promise教程 . get请求访问淘宝IP库 我们先从最基础的get请求开始,get请求的地址为淘宝IP地址库,里面有访问接口的说明.请求代码如下所

React Native(十五)&mdash;&mdash;RN中的分享功能

终于,终于,可以总结自己使用RN时的分享功能了-- 为什么呢?且听我慢慢道来吧: 从刚开始接触React Native(2017年9月中旬)就着手于分享功能,直到自己参与公司的rn项目开发中,再到现在几乎"竣工"的过程中,这一路的"艰辛"估计也只有自己能体会到了吧.其实自己并不喜欢抱怨,也不喜欢把负能量带给身边的朋友,因此在遇到问题后,都是竭尽全力的攻克它,也许会"废寝忘食",也许是"徒劳无功",即使中间道路实在太曲折,但庆幸

【REACT NATIVE 系列教程之八】不使用NAVIGATOR实现切换(页面)场景的两种形式(逻辑与MODAL)

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2285.html 在第五篇中介绍了使用导航Navigator进行(页面)场景的切换,但是对于一些需求其实是无法满足,或者说太浪费.例如: 1. 只是想做一个很简单的页面切换,并不需要记录从哪来-也不需要手势滑屏返回等,这时使用导航Navigator太浪费了. 2. 假设: a) 有个View 包括一个Navigato

菜鸟窝React Native 视频系列教程

菜鸟窝React Native 视频系列教程 交流QQ群:576089067 Hi,我是RichardCao,现任新美大酒店旅游事业群的Android Developer.15年加入饿了么即时配送BU,后负责蜂鸟众包Android端,期间引入react-native技术,作为国内react-native 与 Android混合开发的早期商业项目,具有一定经验,同时也是react-native开源项目reading(https://github.com/attentiveness/reading)

【REACT NATIVE 系列教程之五】NAVIGATOR(页面导航)的基本使用与传参

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2248.html 今天介绍一种应用开发中常用的负责页面切换及导航功能的组件:Navigator 一:Navigator 对于页面导航其实主要功能就是:每个页面都知道本身应该切换到哪个页面,并且切到的页面会记录从哪里来,如果要返回的话,知道返回到哪个页面.这一切都不需要再用逻辑管理!而且每个页面之间也可以进行参数传递,

【React Native开发】React Native进行签名打包成Apk

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50525976 本文出自:[江清清的博客] (一)前言 [好消息]个人网站已经上线运行,后面博客以及技术干货等精彩文章会同步更新,请大家关注收藏:http://www.lcode.org 前几节课程我们对于React Native的一些基础配置,开发工具以及调试,Android项目移植做了相关讲解,今天一起来学习一下另外一个比较重要的知识点,就是React Nativ

React Native专题-江清清

本React Native讲解专题:主要讲解了React Native开发,由基础环境搭建配置入门,基础,进阶相关讲解. 刚创建的React Native交流8群:533435865  欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送! 关于React Native各种疑难杂症,问题深坑总结方案请点击查看: Mac和Windows安装搭建React Native环境教程如下: Mac OS X版本:Mac OS X安装R

React Native的极简手册

安装入门可以参考:React Native官方文档(http://reactnative.cn/docs/0.31/tutorial.html#content). NodeJS知识储备:参考<NodeJS入门>(https://leanpub.com/nodebeginner-chinese).(尊重知识,请购买原版). 书籍:<React Native入门与实战> 代码示例:30天学习React Native教程(https://github.com/fangwei716/30-

腾讯优测优分享 | 探索react native首屏渲染最佳实践

腾讯优测是专业的移动云测试平台,旗下的优分享不定时提供大量移动研发及测试相关的干货~此文主要与以下内容相关,希望对大家有帮助. react native给了我们使用javascript开发原生app的能力,在使用react native完成兴趣部落安卓端发现tab改造后,我们开始对由react native实现的界面进行持续优化.目标只有一个,在享受react native带来的新特性的同时,在体验上无限逼近原生实现.作为一名前端开发,本文会从前端角度,探索react native首屏渲染最佳实