[技術博客]使用PanResponder實現響應左右滑動手勢

在實現用戶左右滑動完成不一樣操做時,使用react-native的官方API——PanResponder響應用戶手勢操做。react

PanResponder介紹

PanResponder中文文檔android

PanResponder類能夠將多點觸摸操做協調成一個手勢。它使得一個單點觸摸能夠接受更多的觸摸操做,也能夠用於識別簡單的多點觸摸手勢。react-native

默認狀況下PanResponder會經過InteractionManager來阻止長時間運行的 JS 事件打斷當前的手勢活動。函數

它提供了一個對觸摸響應系統響應器的可預測的包裝。對於每個處理函數,它在原生事件以外提供了一個新的gestureState對象:測試

onPanResponderMove: (event, gestureState) => {}

基本用法

componentWillMount: function() {
    this._panResponder = PanResponder.create({
      // 要求成爲響應者:
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

      onPanResponderGrant: (evt, gestureState) => {
        // 開始手勢操做。給用戶一些視覺反饋,讓他們知道發生了什麼事情!

        // gestureState.{x,y} 如今會被設置爲0
      },
      onPanResponderMove: (evt, gestureState) => {
        // 最近一次的移動距離爲gestureState.move{X,Y}

        // 從成爲響應者開始時的累計手勢移動距離爲gestureState.d{x,y}
      },
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onPanResponderRelease: (evt, gestureState) => {
        // 用戶放開了全部的觸摸點,且此時視圖已經成爲了響應者。
        // 通常來講這意味着一個手勢操做已經成功完成。
      },
      onPanResponderTerminate: (evt, gestureState) => {
        // 另外一個組件已經成爲了新的響應者,因此當前手勢將被取消。
      },
      onShouldBlockNativeResponder: (evt, gestureState) => {
        // 返回一個布爾值,決定當前組件是否應該阻止原生組件成爲JS響應者
        // 默認返回true。目前暫時只支持android。
        return true;
      },
    });
  },

  render: function() {
    return (
      <View {...this._panResponder.panHandlers} />
    );
  },

這裏僅介紹項目中使用到的兩個屬性,onMoveShouldSetPanResponderonPanResponderReleasethis

  • onMoveShouldSetPanResponder:移動時根據此屬性冒泡詢問本元素是否得到手勢權
  • onPanResponderRelease:用戶放開全部觸摸點且本元素已成爲響應者時將執行的函數

一個gestureState對象有以下的字段:code

  • stateID - 觸摸狀態的 ID。在屏幕上有至少一個觸摸點的狀況下,這個 ID 會一直有效。
  • moveX - 最近一次移動時的屏幕橫座標
  • moveY - 最近一次移動時的屏幕縱座標
  • x0 - 當響應器產生時的屏幕座標
  • y0 - 當響應器產生時的屏幕座標
  • dx - 從觸摸操做開始時的累計橫向路程
  • dy - 從觸摸操做開始時的累計縱向路程
  • vx - 當前的橫向移動速度
  • vy - 當前的縱向移動速度
  • numberActiveTouches - 當前在屏幕上的有效觸摸點的數量

在項目中的使用

/* 渲染一個收藏項數據 */
_renderItem = (item) => {
    let item1 = item;
    var Id = item1.item.key;

    let _panResponder = PanResponder.create({
        onMoveShouldSetPanResponder: (evt, gestureState) => {
            /* 這裏僅當用戶滑動的距離較長才響應用戶操做,考慮實際用戶點擊是手指的一片區域,而不是測試時的鼠標單擊,實際使用時即便是單擊也可能有必定的位移 */
            if(gestureState.dx < -screenWidth*0.1 || gestureState.dx > screenWidth*0.1){
                return true;
            }
            else{
                return false;
            }
        },
        onPanResponderRelease: (evt, gestureState)=>{
            if(gestureState.dx < 0) {
                /* 左滑刪除該項收藏 */
                this._onPressDelBookmarks(WzLinkId);
            }
            else{
                /* 右滑編輯收藏 */
                this._onPressEditBookmarks(WzLinkId);
            }
        },
    });

    return(
        <View style={flatStylesWithAvatar.cell} {..._panResponder.panHandlers}>
            <TouchableOpacity style = {flatStylesWithAvatar.listcontainer}
             onPress={()=>console.log('單擊了該項')}
            >
            具體內容
            </TouchableOpacity>
        </View>
    )
};

這裏對列表中的每一項都建立一個PanResponder對象,綁定不一樣的操做。component

相關文章
相關標籤/搜索