sumini dev

posts

RN Gesture Handler : Gesture Handler란? (2)

profile-image

Choi su min

소개

Gesture handler는 RNGH의 핵심 block이다. 이를 통해 우리는 Javascript + React Component로 Native touch system을 구현하고 조작할 수 있다.

각 handler는 하나의 gesture(pan, pinch, etc.)와, 관련된 event 정보(translation, scale, etc.)들을 제공한다.

Handler는 UI thread에서 작동하기 때문에, JS thread가 block되어도 영향을 받지 않는다.

Handler의 상태

각 handler는 각자의 상태를 갖는다. Touch stream을 입력 받으며, 입력에 따라 상태를 전환한다.

Gesture가 시작하는 순간, 해당 gesture과 관련된 handler들이 선택되며, 발생하는 모든 touch event들이 선택된 모든 handler들에게 전달된다.

한 gesture가 active되면, 다른 모든 gesture들은 취소된다.

View와의 관계

Gesture Handler 컴포넌트는 렌더 hierarchy내에 View로 구현되지 않는다. 대신, 라이브러리 고유의 레지스터리를 가지며 View와 연결만 된다.

따라서 Gesture Handler 컴포넌트를 사용할 땐 꼭 View를 child로 배치해야한다.

Gesture Handler 컴포넌트가 hierarchy내에 존재하지 않기 때문에, 발생한 event들이 child에 배치된 View에 걸리기 때문이다.

Gesture Handler의 종류

Gesture의 종류 (discrete, continuous)

  1. Continuous

오랜 시간동안 활성화(active)될 수 있으며, gesture가 끝날때까지 Gesture event stream을 생성한다. (ex:PanGestureHandler)

  1. Discrete

활성화(active)된 순간 즉시 종료된다. (ex: LongPressGestureHandler)

(onGestureEvent는 continuous gesture handler에서만 발생한다.)

Handler 중첩

Handler 컴포넌트를 중첩시킬 수 있다. 가장 내부의 handler는 View를 포함해야한다.

class Multitap extends Component {
  render() {
    return (
      <LongPressGestureHandler
        onHandlerStateChange={this._onLongpress}
        minDurationMs={800}
      >
        <TapGestureHandler
          onHandlerStateChange={this._onSingleTap}
          waitFor={this.doubleTapRef}
        >
          <TapGestureHandler
            ref={this.doubleTapRef}
            onHandlerStateChange={this._onDoubleTap}
            numberOfTaps={2}
          >
            <View style={styles.box} />
          </TapGestureHandler>
        </TapGestureHandler>
      </LongPressGestureHandler>
    );
  }
}

Events with useNativeDriver

Handler component가 child view에 종속적이기 때문에, Animated.event를 사용할 때 두 gesture를 직접 중첩할 수 없다. Animated.View를 handler 사이에 배치해 해결할 수 있다.

// BAD
const PanAndRotate = () => (
  <PanGestureHandler onGestureEvent={Animated.event({ ... }, { useNativeDriver: true })}>
    <RotationGestureHandler onGestureEvent={Animated.event({ ... }, { useNativeDriver: true })}>
      <Animated.View style={animatedStyles}/>
    </RotationGestureHandler>
  </PanGestureHandler>
);

// GOOD : Animated.View를 삽입했다.
const PanAndRotate = () => (
  <PanGestureHandler onGestureEvent={Animated.event({ ... }, { useNativeDriver: true })}>
    <Animated.View>
      <RotationGestureHandler onGestureEvent={Animated.event({ ... }, { useNativeDriver: true })}>
        <Animated.View style={animatedStyles}/>
      </RotationGestureHandler>
    </Animated.View>
  </PanGestureHandler>
);

또, event가 children node에 걸리기 때문에 useNativeDriver + Animated.event를 사용할 경우 children node는 Animated.View여야한다.

class Draggable extends Component {
  render() {
    return (
      <PanGestureHandler onGestureEvent={Animated.event({ ... }, { useNativeDriver: true })}>
        <Animated.View style={animatedStyles} /> {/* <-- NEEDS TO BE Animated.View */}
      </PanGestureHandler>
    );
  }
};

React Native Components

NativeViewGestureHandler로 감싼 리액트 네이티브 컴포넌트들을 제공한다.

  • ScrollView
  • FlatList
  • Switch
  • TextInput
  • DrawerLayoutAndroid (Android only)

REACT-NATIVE8개 더보기

모든 글 보기

이전 글

RN Gesture Handler : 시작하기 (1)

다음 글

RN Gesture Handler : Handler의 상태 (3)

profile-image

Choi su min

Sogang Univ.

AWESOME.DEV Lead

Anyang, Gyeong-gi, Republic of Korea

github-iconmail-iconrss-icon