将 UIView 移动限制为仅垂直或水平轴

Limit UIView movement to only vertical or horizontal axis

我正在使用 PanGestureRecognizer 并在 UIGestureRecognizerStateChanged 中让用户手指移动屏幕上的视图。我将其用于 Tinder 之类的滑动手势,现在我想将视图的移动限制在水平轴或垂直轴上,无论用户开始滑动的方向如何。我一直在上下搜索,但在这里找不到合适的东西。

有没有什么聪明的方法可以根据用户开始滑动视图的方向来限制轴的移动?

非常感谢!

更新:这是移动视图的当前代码:

- (void)dragged:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGFloat xDistance = [gestureRecognizer translationInView:self].x;
    CGFloat yDistance = [gestureRecognizer translationInView:self].y;
//    xDistance = 0;

    [parentView dragged:yDistance];

    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStateBegan:{
            self.originalPoint = self.center;
            break;
        };
        case UIGestureRecognizerStateChanged:{
            CGFloat rotationAngel = 0;
            CGFloat scale = 1;//MAX(scaleStrength, 0.93);
            CGAffineTransform transform = CGAffineTransformMakeRotation(rotationAngel);
            CGAffineTransform scaleTransform = CGAffineTransformScale(transform, scale, scale);
            self.transform = scaleTransform;
            self.center = CGPointMake(self.originalPoint.x + xDistance, self.originalPoint.y + yDistance);
            ...
            break;
        };
        case UIGestureRecognizerStateEnded: {
            float moveDistAction = 60;
            if (yDistance > moveDistAction) {
                // view swiped down
                ...
            } else if (yDistance < -moveDistAction) {//100 150
                // view swiped up 
                ...
            } else {
                // dragging cancelled
                ...
            }
            break;
        };
        case UIGestureRecognizerStatePossible:break;
        case UIGestureRecognizerStateCancelled:break;
        case UIGestureRecognizerStateFailed:break;
    }
}

gestureRecognizerShouldBegin:你可以知道那个方向:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer {
    CGPoint translation = [gestureRecognizer translationInView:self.view];
    self.isVerticalPan = fabs(translation.y) > fabs(translation.x); // BOOL property

    return YES;
}

然后在 UIGestureRecognizerStateChanged 上你可以做这样的事情,基于 isVerticalPan 属性:

CGPoint translation = [gesture translationInView:self.view];
CGPoint displacement = (self.isVerticalPan) ? CGPointMake(0, translation.y) : CGPointMake(translation.x, 0);

self.viewToMove.transform = CGAffineTransformMakeTranslation(displacement.x, displacement.y);

您可以通过实施 gestureRecognizerShouldBegin: 委托方法来做到这一点。在下面的实现中,我正在检查大约 20 度的水平滑动。但是,您可以检查水平或垂直滑动。 (我会使用一些小角度,因为用户很难完全沿着一条直线移动。)

- (BOOL) gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    // Ensure that the user is only panning mostly horizontally
    // This allows the view to be placed in a scrollview that scrolls vertically
    // Up/Down drags in the body of the view will be passed to the scroll view
    if (gestureRecognizer == self.panGesture) {

        CGPoint velocity = [self.panGesture velocityInView:self.panGesture.view];

        double radian = atan(velocity.y/velocity.x);
        double degree = radian * 180 / M_PI;

        double thresholdAngle = 20.0;
        if (fabs(degree) > thresholdAngle) {
            return NO;
        }
    }
    return YES;
}

免责声明:我很确定我在这里的某个地方找到了这个解决方案,但我找不到。所以,向这个问题的原始解决者道歉...