onHandlerStateChange = ({nativeEvent}) => {
        if (nativeEvent.oldState === GestureState.ACTIVE) {
            const {translationY, velocityY} = nativeEvent;
            const {allowStayMiddle} = this.props;
            const {lastSnap} = this.state;
            const isGoingDown = translationY > 0;
            const translation = translationY - this.lastScrollYValue;

            const endOffsetY = lastSnap + translation;
            let destSnapPoint = this.snapPoints[0];

            if (Math.abs(translationY) < 50 && allowStayMiddle) {
                // Only drag the panel after moving 50 or more points
                destSnapPoint = lastSnap;
            } else if (isGoingDown && !allowStayMiddle) {
                // Just close the panel if the user pans down and we can't snap to the middle
                destSnapPoint = this.snapPoints[2];
            } else if (isGoingDown) {
                destSnapPoint = this.snapPoints.find((s) => s >= endOffsetY);
            } else {
                destSnapPoint = this.snapPoints.find((s) => s <= endOffsetY);
            }

            if (destSnapPoint) {
                this.translateYOffset.extractOffset();
                this.translateYOffset.setValue(translationY);
                this.translateYOffset.flattenOffset();
                this.dragY.setValue(0);

                if (destSnapPoint === this.snapPoints[2]) {
                    this.closeWithAnimation();
                } else {
                    Animated.spring(this.translateYOffset, {
                        velocity: velocityY,
                        tension: 68,
                        friction: 12,
                        toValue: destSnapPoint,
                        useNativeDriver: true,
                    }).start(() => {
                        this.setState({lastSnap: destSnapPoint});

                        // When dragging down the panel when is fully open reset the scrollView to the top
                        if (isGoingDown && destSnapPoint !== this.snapPoints[0]) {
                            this.scrollToTop();
                        }
                    });
                }
            } else {
                Animated.spring(this.translateYOffset, {
                    velocity: velocityY,
                    tension: 68,
                    friction: 12,
                    toValue: lastSnap,
                    useNativeDriver: true,
                }).start();
            }
        }
    };
  _onHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      const { height, width } = this.state;

      const posX = this._lastOffset.x + event.nativeEvent.translationX;
      const posY = this._lastOffset.y + event.nativeEvent.translationY;

      const distFromTop = posY;
      const distFromBottom = height - posY - BOX_SIZE;
      const distFromLeft = posX;
      const distFromRight = width - posX - BOX_SIZE;

      this._lastOffset = { x: posX, y: posY };

      this._dragX.flattenOffset();
      this._dragY.flattenOffset();

      const minDist = Math.min(
        distFromTop,
        distFromBottom,
        distFromLeft,
        distFromRight
      );
      if (distFromTop === minDist) {
        this._dragY.setValue(-BOX_SIZE / 4);
        this._lastOffset.y = -BOX_SIZE / 4;
      } else if (distFromBottom === minDist) {
        this._dragY.setValue(height - BOX_SIZE / 2);
        this._lastOffset.y = height - BOX_SIZE / 2;
      } else if (distFromLeft === minDist) {
        this._dragX.setValue(-BOX_SIZE / 2);
        this._lastOffset.x = -BOX_SIZE / 2;
      } else if (distFromRight === minDist) {
        this._dragX.setValue(width - BOX_SIZE / 2);
        this._lastOffset.x = width - BOX_SIZE / 2;
      }

      this._dragX.extractOffset();
      this._dragY.extractOffset();
    }
  };