【React Native 系列教程之一】触摸事件的两种形式与四种Touchable组件详解
ytbf0203
8年前
<p>本文是RN(React Native)系列教程第一篇,当然也要给自己的群做个广告:</p> <p>React Native @Himi :126100395 刚创建的群,欢迎一起学习、讨论、进步。</p> <p>本文主要讲解两点:</p> <p>1. PanResponder:触摸事件,用以获取用户手指所在屏幕的坐标(x,y)或触发、或滑动、或抬起几种事件通知。</p> <p>2. Touchable:React为我们封装好的触摸组件。引用原文:“响应系统用起来可能比较复杂。所以我们提供了一个抽象的 Touchable 实现,用来做“可触控”的组件。这一实现利用了响应系统,使得你可以简单地以声明的方式来配置触控处理。”</p> <h2>一:触摸事件各事件响应与坐标获取</h2> <p>1. 在import React 中添加要使用的触摸组件:</p> <pre> <code class="language-javascript">importReact, { ... PanResponder,//触摸必要的组件 ... } from 'react-native'; </code></pre> <p>2. 声明:</p> <pre> <code class="language-javascript">constructor(props) { super(props); this.state = { eventName:'', pos: '', }; this.myPanResponder={} } </code></pre> <p>这里先声明了两个变量posX,posY用于显示坐标用,另外声明了一个 myPanResponder 用于后面的触摸事件。</p> <p>3. 创建、设置与响应</p> <pre> <code class="language-javascript">componentWillMount() { this.myPanResponder = PanResponder.create({ //要求成为响应者: onStartShouldSetPanResponder: (evt, gestureState) => true, onStartShouldSetPanResponderCapture: (evt, gestureState) => true, onMoveShouldSetPanResponder: (evt, gestureState) => true, onMoveShouldSetPanResponderCapture: (evt, gestureState) => true, onPanResponderTerminationRequest: (evt, gestureState) => true, //响应对应事件后的处理: onPanResponderGrant: (evt, gestureState) => { this.state.eventName='触摸开始'; this.forceUpdate(); }, onPanResponderMove: (evt, gestureState) => { var _pos = 'x:' + gestureState.moveX + ',y:' + gestureState.moveY; this.setState( {eventName:'移动',pos : _pos} ); }, onPanResponderRelease: (evt, gestureState) => { this.setState( {eventName:'抬手'} ); }, onPanResponderTerminate: (evt, gestureState) => { this.setState( {eventName:'另一个组件已经成为了新的响应者'} ) }, }); } </code></pre> <p>以上代码分为3部分,先创建,然后对需要追踪的事件进行设置响应,最后重写响应的事件进行处理即可。</p> <p>需要注意的:绑定到componentDidMount的话可能会失效,需要在componentWillMount处预先创建手势响应器</p> <p>4. 为要响应的View进行设置</p> <pre> <code class="language-javascript">{...this.myPanResponder.panHandlers} </code></pre> <p>5. 完善Render函数:</p> <pre> <code class="language-javascript">render() { return ( <Viewstyle={styles.himiViewStyle} {...this.myPanResponder.panHandlers} > <Text style={styles.himiTextStyle}>HimiReactNative 教程</Text> <Viewstyle={styles.container}> <Text style={styles.text}>{this.state.eventName}</Text> <Text style={styles.text}>{this.state.pos}</Text> </View> </View> )} </code></pre> <p>6.用到的布局和样式:</p> <pre> <code class="language-javascript">var styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, text: { color:'#f00', fontSize:30, }, himiViewStyle:{ flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, himiTextStyle:{ color:'#f00', fontSize:30, marginTop:70, }, }); </code></pre> <p>效果如下:(点击查看动态效果)</p> <p><img src="https://simg.open-open.com/show/d293716a8b4565a26da57d4eb69e73fd.gif"></p> <p>如上是第一种形式,下面我们简单说下如何使用第二种形式:</p> <pre> <code class="language-javascript">componentWillMount() { this.myPanResponder = PanResponder.create({ //*********************第二种触摸的形式*************************** //类似 shouldComponentUpdate,监听手势开始按下的事件,返回一个boolean决定是否启用当前手势响应器 onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder.bind(this), //监听手势移动的事件,返回一个boolean决定是否启用当前手势响应器 onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder.bind(this), //手势开始处理 onPanResponderGrant: this._handlePanResponderGrant.bind(this), //手势移动时的处理 onPanResponderMove: this._handlePanResponderMove.bind(this), //用户放开所有触点时的处理 onPanResponderRelease: this._handlePanResponderRelease.bind(this), //另一个组件成了手势响应器时(当前组件手势结束)的处理 onPanResponderTerminate: this._handlePanResponderEnd.bind(this) }); } _handleStartShouldSetPanResponder(e, gestureState) { //返回一个boolean决定是否启用当前手势响应器 return true; } _handleMoveShouldSetPanResponder(e, gestureState) { return true; } _handlePanResponderGrant(e, gestureState) { this.setState({ eventName : 'Start' }) } _handlePanResponderRelease(e, gestureState) { this.setState({ eventName : 'End' }) } _handlePanResponderMove(e, gestureState) { var _pos = 'x:' + gestureState.moveX + ',y:' + gestureState.moveY; this.setState({ eventName : 'Move:', pos : _pos }) } _handlePanResponderEnd(e, gestureState) { this.setState({ eventName : '另一个组件成了手势响应器时(当前组件触摸结束)的处理' }) } </code></pre> <p>第二种形式就是将触摸响应绑定到我们自定义的函数,其他没有基本没区别。改动只有两点:</p> <p>1. 绑定时修改成将触摸事件的回调绑定到我们自定义函数。</p> <p>2. 添加每个响应的自定义函数。</p> <p>效果如下:(点击查看动态效果)</p> <p><img src="https://simg.open-open.com/show/1c91a83911db39e5c92272acd81b9667.gif"></p> <h2>二:四种 Touchable 触摸组件 </h2> <p>Touchable 一共有四种形式:</p> <p>TouchableHighlight: 当按下的时候,封装的视图的不透明度会降低,同时会有一个底层的颜色透过而被用户看到,使得视图变暗或变亮。</p> <p>TouchableNativeFeedback:(仅限Android平台) 在Android设备上,这个组件利用原生状态来渲染触摸的反馈。</p> <p>TouchableOpacity: 当按下的时候,封装的视图的不透明度会降低。这个过程并不会真正改变视图层级,大部分情况下很容易添加到应用中而不会带来一些奇怪的副作用。</p> <p>TouchableWithoutFeedback: 除非你有一个很好的理由,否则不要用这个组件。所有能够响应触屏操作的元素在触屏后都应该有一个视觉上的反馈(然而本组件没有任何视觉反馈),仍会触发触摸事件的响应</p> <p>1. 添加Touchable的四种组件</p> <pre> <code class="language-javascript">importReact, { ... Image, Alert, TouchableHighlight, TouchableNativeFeedback, TouchableOpacity, TouchableWithoutFeedback, ... } from 'react-native'; </code></pre> <p>Himi这里还添加了Image和Alert两个组件:</p> <p>Image 是图片组件,这里是为了测试效果,将Touchable发生在图片</p> <p>Alert 弹窗提示组件,是为了通过弹窗,更好的展示出事件响应效果</p> <p>2. 在Render添加如下:</p> <pre> <code class="language-javascript"><Viewstyle={styles.container}> <TouchableHighlight underlayColor='#4169e1' onPress={this.test} > <Image source={require('./res/himi.png')} style={{width: 70, height: 70}} /> </TouchableHighlight> <TouchableOpacity activeOpacity={0.5} onPress={()=>{Alert.alert('Himi', ' TouchableOpacity ');} } > <Image source={require('./res/himi.png')} style={{width: 70, height: 70}} /> </TouchableOpacity> <TouchableWithoutFeedback underlayColor='#4169e1' activeOpacity={0.5} onPress={()=>{Alert.alert('Himi', ' TouchableWithoutFeedback ');} } > <Image source={require('./res/himi.png')} style={{width: 70, height: 70}} /> </TouchableWithoutFeedback> </View> </code></pre> <p>由于Himi写博客时在Mac下,那么如下我们来创建除仅限Android的TouchableNativeFeedback之外的三种形式。</p> <p>根据反馈的形式,大家可以自行设置其透明度、背景色、样式等。</p> <p>效果图如下:(点击查看动态图)</p> <p><img src="https://simg.open-open.com/show/b4ddaa637a243c5c4838836aa6116968.gif"></p> <p> </p> <p>来自: <a href="/misc/goto?guid=4959673712240875903" rel="nofollow">http://www.himigame.com/react-native/2203.html</a></p> <p> </p>