Почему два отдельных компонента совместно используют состояние в React Native? - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь реализовать функциональность ползунка мультитач (на основе примера кода, предоставленного обработчиком жестов Native React).

Я обнаружил, что когда я создаю два компонента TapOrPan, они работают индивидуально, но состояние слайдера является общим, если одновременно коснуться обоих слайдеров.

Почему это происходит, учитывая, что я использую два отдельных компонента? Чего мне не хватает?

Экспо-ссылка для отладки: https://snack.expo.io/aPLAoFWar

import React, { Component } from 'react';
import { Animated, Dimensions, StyleSheet, Text, View } from 'react-native';
import {
  PanGestureHandler,
  TapGestureHandler,
  ScrollView,
  State,
} from 'react-native-gesture-handler';

export function TapOrPan({width, radius}) {
  const tapRef = React.createRef();
  const panRef = React.createRef();

  const _id = parseInt(Math.random() * 100);
  const _touchX = new Animated.Value(width / 2 - radius);
  const _circleValue = new Animated.Value(-radius);
  const _translateX = Animated.add(_touchX, _circleValue);
  const _onPanGestureEvent = Animated.event(
    [{nativeEvent: {x: _touchX}}],
    {useNativeDriver: true}
  );

  const styles = StyleSheet.create({
    horizontalPan: {
      backgroundColor: '#777',
      height: 120,
      justifyContent: 'center',
      marginVertical: 10,
    },
    circle: {
      backgroundColor: '#fff',
      borderRadius: radius,
      height: radius * 2,
      width: radius * 2,
    },
    wrapper: {
      flex: 1,
    },
  });

  function _onTapHandlerStateChange({ nativeEvent }) {
    console.log(_id.toString() + ": " + JSON.stringify(nativeEvent));
    if (nativeEvent.oldState === State.ACTIVE) {
      // Once tap happened we set the position of the circle under the tapped spot
      _touchX.setValue(nativeEvent.x);
    }
  }

  return (
    <TapGestureHandler
      ref={tapRef}
      onHandlerStateChange={_onTapHandlerStateChange}
      >
      <Animated.View style={styles.wrapper}>
        <PanGestureHandler
          ref={panRef}
          activeOffsetX={[0, 0]}
          onGestureEvent={_onPanGestureEvent}
          >
          <Animated.View style={styles.horizontalPan}>
            <Animated.View
              style={[
                styles.circle,
                {transform: [{translateX: _translateX}]},
              ]}
            />
          </Animated.View>
        </PanGestureHandler>
      </Animated.View>
    </TapGestureHandler>
  );
}

export default function Example() {
  const windowWidth = Dimensions.get('window').width;

  return (
    <ScrollView>
      <TapOrPan width={windowWidth} radius={30} />
      <TapOrPan width={windowWidth} radius={30} />
    </ScrollView>
  );
}

1 Ответ

0 голосов
/ 01 мая 2020

Если подумать, что это не будет работать так, как вы хотите. Не существует двух координат для двух разных пальцев, движущихся в разных направлениях. Существует одна координата некоторой точки, которая рассчитывается по всем координатам вашего пальца (разные на разных платформах). https://github.com/software-mansion/react-native-gesture-handler/blob/d3c8ff130e7d925dae7cec149098c5d042a00120/android/lib/src/main/java/com/swmansion/gesturehandler/PanGestureHandler.java#L44

...