React Native Animated PanResponder реверсирует на втором входе - PullRequest
0 голосов
/ 24 мая 2018

Я получил компонент, использующий PanResponder в сочетании с Animated от React Native API.Код моего компонента:

import React, { Component } from 'react';
import { Animated, PanResponder } from 'react-native';

import { SVG } from '../';
import { Icon, LockContainer, StatusCircle } from './styled';

class VehicleLock extends Component {
  state = {
    pan: new Animated.ValueXY({ x: 9, y: 16 }),
  };

  componentWillMount() {
    this.animatedValueY = 0;

    this.minYValue = 16;
    this.maxYValue = 175;

    this.state.pan.y.addListener((value) => {
      this.animatedValueY = value.value;
    });

    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponderCapture: () => true,
      onMoveShouldSetPanResponderCapture: () => true,

      onPanResponderGrant: (evt, gestureState) => {
        this.state.pan.setOffset({ x: 0, y: 0 });
        // this.state.pan.setOffset(this.state.pan.__getValue());
        this.state.pan.setValue({ x: 9, y: this.minYValue });
      },
      onPanResponderMove: (evt, gestureState) => {
        // deltaY: amount of pixels moved vertically since the beginning of the gesture
        let newY = gestureState.dy;

        if (newY < this.minYValue) {
          newY = this.minYValue;
        } else if (newY > this.maxYValue) {
          newY = this.maxYValue;
        }

        Animated.event([null, {
          dy: this.state.pan.y,
        }])(evt, {
          dy: newY,
        });
      },
      onPanResponderRelease: (evt, gestureState) => {
        let newY = this.minYValue;
        const releaseY = gestureState.dy;

        if (releaseY > 83) {
          newY = this.maxYValue;
        }

        Animated.spring(this.state.pan, {
          toValue: {
            x: 9,
            y: newY,
          },
        }).start();
      },
    });
  }

  componentWillUnmount() {
    this.state.pan.x.removeAllListeners();
    this.state.pan.y.removeAllListeners();
  }

  render() {
    const customStyles = {
      ...this.state.pan.getLayout(),
      position: 'absolute',
      zIndex: 10,
      transform: [
        {
          rotate: this.state.pan.y.interpolate({
            inputRange: [this.minYValue, this.maxYValue],
            outputRange: ['0deg', '180deg'],
          }),
        },
      ],
    };

    return (
      <LockContainer>
        <SVG icon="lock_open" width={16} height={21} />

        <Animated.View
          {...this.panResponder.panHandlers}
          style={customStyles}
        >
          <StatusCircle>
            <Icon>
              <SVG icon="arrow_down" width={23} height={23} />
            </Icon>
          </StatusCircle>
        </Animated.View>

        <SVG icon="lock_closed" width={16} height={21} />
      </LockContainer>
    );
  }
}

export default VehicleLock;

Как вы можете видеть в моем коде, я анимирую значение Y с границей.Он должен оставаться в поле между определенными значениями.Как только пользователи отпускают перетаскивание, и оно превышает половину максимального значения Y, оно анимируется до максимального значения.

Это работает без каких-либо проблем, но при втором взаимодействии я хотел бы изменить действие.Поэтому вместо того, чтобы идти вниз, оно должно идти вверх.К сожалению, при выпуске значение Y сбрасывается.

Как вы можете видеть из комментария в моем коде, я знаю, что движение основано на дельте, поэтому значение Y перемещено с момента начала взаимодействия.Это объясняется в этом замечательном комментарии PanResponder привязывает Animated.View к исходной позиции при втором перетаскивании .

Хотя я не знаю, как это исправить.Здесь вы можете увидеть мое текущее поведение: enter image description here

На втором входе элемент возвращается обратно вверх.Что является ожидаемым поведением.Как пишет @jevakallio в своем комментарии, вы можете сбросить значения смещения в onPanResponderGrant.Когда я это делаю (закомментировано), элемент сбрасывает значения, но при втором взаимодействии он будет анимировать вне контейнера.Так что в этом случае 0 - это maxYValue, и он анимирует 175 за пределами контейнера до дна.

Как я могу сделать перевернутый анимированный снаружи обратно наверх?Кажется, я этого не понимаю.Заранее спасибо!

1 Ответ

0 голосов
/ 25 мая 2018

Согласно Документы Panresponder onPanResponderGrant должны указывать начало жеста.Таким образом, если вы установите this.state.pan.setOffset и this.state.pan.setValue на этом этапе, он будет сбрасываться с началом каждого жеста.Попробуйте файл console.log в onPanResponderGrant и посмотрите, что произойдет.

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

Из документов PanResponder:

onPanResponderGrant: (evt, gestureState) => {
    // The gesture has started. Show visual feedback so the user knows
    // what is happening!

    // gestureState.d{x,y} will be set to zero now
  },
...