Реагируйте на встроенное перетаскивание анимированных. - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть круги, я должен заставить эти круги двигаться в отведенном для этого месте, и если на одном из них происходит длительное давление, то это вызывает событие.

Я сделал это, но это не такЭто, кажется, работает очень хорошо.

Я использовал Animated.View с TouchableWithoutFeedback внутри, который использует функцию события onLongPress, но в некоторых случаях это работает, в другом ничего не работает.

Можете ли вы дать мне несколько советов по этому поводу?

Ссылка: перекусить

Код:

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

class Draggable extends Component {
  constructor(props) {
    super(props);

    this.state = {
      showDraggable: true,
      dropAreaValues: null,
      pan: new Animated.ValueXY(),
      opacity: new Animated.Value(1),
    };
  }

  componentWillMount() {
    this._val = { x: 0, y: 0 };
    this.state.pan.addListener(value => (this._val = value));

    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (e, gesture) => true,
      onPanResponderGrant: (e, gesture) => {
        this.state.pan.setOffset({
          x: this._val.x,
          y: this._val.y,
        });
        this.state.pan.setValue({ x: 0, y: 0 });
      },
      onPanResponderMove: Animated.event([
        null,
        { dx: this.state.pan.x, dy: this.state.pan.y },
      ]),
      onPanResponderRelease: (e, gesture) => {
        if (this.isDropArea(gesture)) {
          Animated.timing(this.state.opacity, {
            toValue: 0,
            duration: 1000,
          }).start(() =>
            this.setState({
              showDraggable: false,
            })
          );
        }
      },
    });
  }

  isDropArea(gesture) {
    return gesture.moveY < 200;
  }

  render() {
    return (
      <View style={{ width: '20%', alignItems: 'center' }}>
        {this.renderDraggable()}
      </View>
    );
  }

  renderDraggable() {
    const panStyle = {
      transform: this.state.pan.getTranslateTransform(),
    };
    if (this.state.showDraggable) {
      return (
        <View style={{ position: 'absolute' }}>
          <Animated.View
            {...this.panResponder.panHandlers}
            style={[panStyle, styles.circle, { opacity: this.state.opacity }]}>
            <TouchableWithoutFeedback
              style={{}}
              onLongPress={() => console.log('el:', this.props.id)}>
                <Text style={styles.text}>{this.props.id}</Text>
            </TouchableWithoutFeedback>
          </Animated.View>
        </View>
      );
    }
  }
}

export default class App extends Component {
  render() {
    return (
      <View style={styles.mainContainer}>
        <View style={styles.dropZone}>
          <Text style={styles.text}>Drop them here!.</Text>
        </View>
        <View style={styles.ballContainer} />
        <View style={styles.row}>
          <Draggable id={1} />
          <Draggable id={2} />
          <Draggable id={3} />
          <Draggable id={4} />
          <Draggable id={5} />
        </View>
      </View>
    );
  }
}

let CIRCLE_RADIUS = 30;
const styles = StyleSheet.create({
  mainContainer: {
    flex: 1,
  },
  ballContainer: {
    height: 200,
  },
  circle: {
    backgroundColor: 'skyblue',
    width: CIRCLE_RADIUS * 2,
    height: CIRCLE_RADIUS * 2,
    borderRadius: CIRCLE_RADIUS,
  },
  row: {
    flexDirection: 'row',
  },
  dropZone: {
    height: 200,
    backgroundColor: '#00334d',
  },
  text: {
    marginTop: 25,
    marginLeft: 5,
    marginRight: 5,
    textAlign: 'center',
    color: '#fff',
    fontSize: 25,
    fontWeight: 'bold',
  },
});
...