Как установитьOffset для panResponder при использовании хуков? - PullRequest
0 голосов
/ 17 января 2020

Я нашел пример кода, демонстрирующий использование panResponder для действий перетаскивания в реагировать нативно. Вы можете попробовать код в следующей закуске:

https://snack.expo.io/S14RvxJ_L

Проблема, с которой я сталкиваюсь, заключается в том, что, если вы уроните предмет в область опускания, а затем коснитесь это, позиция все время сбрасывается.

Я хочу, чтобы пользователь мог без проблем перетаскивать элемент из области перетаскивания. Итак, еще раз, чтобы уточнить: вы перетащите элемент в область выпадения, и он будет окрашен в красный цвет. Теперь перетащите элемент снова и попробуйте перетащить куда угодно, положение будет сброшено. Я попытался установить начальную позицию круга с помощью крючка, попытался установить y0 и x0 жеста в начале с начальными значениями. До сих пор это не сработало.

На данный момент я обнаружил, что я могу использовать pan.setOffset () в onPanResponderGrant. Но так как панорама создается с помощью useRef (), она изменчива и не может быть изменена, или, что лучше, я не знаю, как.

Как бы я достиг sh, что будет лучшим способом?

import React from 'react';
import { StyleSheet, View, Text, Dimensions, Animated, PanResponder } from 'react-native';

export default function Drag() {
  const dropZoneValues = React.useRef(null);
  const pan = React.useRef(new Animated.ValueXY());
  const [bgColor, setBgColor] = React.useState('#2c3e50');

  const isDropZone = React.useCallback((gesture) => {
    const dz = dropZoneValues.current;
    return gesture.moveY > dz.y && gesture.moveY < dz.y + dz.height;
  }, []);

  const onMove = React.useCallback((_, gesture) => {
    if (isDropZone(gesture)) setBgColor('red');
    else setBgColor('#2c3e50');
  }, [isDropZone]);

  const setDropZoneValues = React.useCallback((event) => {
    dropZoneValues.current = event.nativeEvent.layout;
  });

  const panResponder = React.useMemo(() => PanResponder.create({
    onStartShouldSetPanResponder: () => true,

    onPanResponderMove: Animated.event([null, {
      dx  : pan.current.x,
      dy  : pan.current.y
    }], {
      listener: onMove
    }),
    onPanResponderRelease: (e, gesture) => {
      if (!isDropZone(gesture)) {
        Animated.spring(
          pan.current,
          {toValue:{x:0,y:0}}
        ).start();
      }
    }
  }), []);

  return (
    <View style={styles.mainContainer}>
      <View
        onLayout={setDropZoneValues}
        style={[styles.dropZone, {backgroundColor: bgColor}]}
      >
        <Text style={styles.text}>Drop me here!</Text>
      </View>
      <View style={styles.draggableContainer}>
        <Animated.View
          {...panResponder.panHandlers}
          style={[pan.current.getLayout(), styles.circle]}
        >
          <Text style={styles.text}>Drag me!</Text>
        </Animated.View>
      </View>
    </View>
  );
}

let CIRCLE_RADIUS = 36;
let Window = Dimensions.get('window');
let styles = StyleSheet.create({
  mainContainer: {
    flex: 1
  },
  dropZone: {
    height  : 100,
    backgroundColor:'#2c3e50'
  },
  text        : {
    marginTop   : 25,
    marginLeft  : 5,
    marginRight : 5,
    textAlign   : 'center',
    color       : '#fff'
  },
  draggableContainer: {
    position    : 'absolute',
    top         : Window.height/2 - CIRCLE_RADIUS,
    left        : Window.width/2 - CIRCLE_RADIUS,
  },
  circle: {
    backgroundColor     : '#1abc9c',
    width               : CIRCLE_RADIUS*2,
    height              : CIRCLE_RADIUS*2,
    borderRadius        : CIRCLE_RADIUS
  }
});

(код от: https://github.com/facebook/react-native/issues/25360#issuecomment -505241400 )

1 Ответ

1 голос
/ 25 января 2020

Я наконец решил это

Вы можете увидеть результат здесь: https://snack.expo.io/Bky! LlqbI

Вы должны использовать setOffset и setValue в onPanResponderGrant. pan является изменяемым объектом, но все еще может быть изменен с помощью pan.current.setOffset () или pan.current.setValue (). Наконец, мне пришлось добавить pan.current.flattenOffset в onPanResponderRelease, чтобы сохранить положение для следующего перетаскивания в зоне перетаскивания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...