React Native 五:手勢

來源:互聯網
上載者:User

標籤:

一、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:當前螢幕上的所有觸摸點的集合
五、PanResponder1.除了手勢相應系統之外,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.運行示範如下,由於只能上傳圖片,無法示範動畫,樣式中矩形位於中間,圖中拖動至下方:

React Native 五:手勢

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.