具有垂直拖动手势的水平滚动UIScrollView

9

我希望实现一个UIScrollView,水平滚动浏览滚动视图中的图片,而垂直滚动则执行另一项操作。目前,我有一个UIScrollView,它是分页式的,禁用了垂直滚动,并且可以很好地用于浏览图片,但是我正在疯狂地寻找一种方法来拦截垂直手势并调用自己的方法,而不是让UIScrollView吃掉垂直手势。我已经做到了...

    UIPanGestureRecognizer *panUp = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
[self.scrollView addGestureRecognizer:panUp];
[scrollView.panGestureRecognizer setEnabled:NO];

这让我在handlePanGesture:方法中完全控制平移,但这并不特别有帮助,因为我感觉我实际上会重写所有的滚动逻辑,而我正试图避免这种情况。如果有任何帮助或指导来实现这一点,将不胜感激。

谢谢!


你想用垂直滚动做什么?它是否涉及滚动? - rdelmar
这不涉及滚动。我有一个子视图,我想将其动画化到滚动视图的同一父视图中(滚动视图仅占据父视图的一部分)。 - lramirez135
那我不理解你的陈述:“我觉得我基本上要重写所有滚动逻辑”。你的水平滑动是否正常工作?panUp是否仍然被scrollView拦截? - rdelmar
我知道我来晚了,但将shouldRecognizeSimultaneouslyWithGestureRecognizer设置为return YES会起作用,但是您还必须将您的 pan 手势的.delegate设置为self。我忘记设置委托导致它不能正常工作。我看到您在上面的代码中也没有设置委托。希望这能帮助未来的用户。 - Albert Renshaw
3个回答

10
自 iOS 5 开始,UIScrollView 公开了其 UIPanGestureRecognizer。将你的自定义滑动手势的 delegate 设置为 self,并将手势识别器设为属性或 ivar,然后使你的类符合 <UIGestureRecognizerDelegate> 协议。接下来,实现 UIGestureRecognizerDelegate– gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([gestureRecognizer isEqual:self.swipe] && [otherGestureRecognizer isEqual:self.scrollView.panGestureRecognizer])
    {
         return NO;
    }
    return YES; // the default for this method
}

我喜欢这个答案,因为它通过平移手势将更多的控制权交到了我的手中,而不仅仅是简单的滑动。我曾经遇到过我的uitableview与左右平移手势同时工作的问题。这个方法解决了我的问题。 - smisiewicz
1
不起作用!otherGestureRecognizerUIScrollViewDelayedTouchesBeganGestureRecognizer,当然不等于self.scrollView.panGestureRecognizer - Vyachaslav Gerchicov
该方法将为每个手势识别器调用,这些识别器需要与您的对象作为代理的任何手势识别器同时识别。 - Zev Eisenberg

10
我添加了一个 UIPanGestureRecognizer,然后像这样设置gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([gestureRecognizer isEqual:self.panGesture] && [otherGestureRecognizer isEqual:self.collectionView.panGestureRecognizer]){
        return YES;
    }
    return NO;
}

我还在gestureRecognizerShouldBegin:中添加了一个检查。

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if ([gestureRecognizer isEqual:self.panGesture]) {
        if (gestureRecognizer.numberOfTouches > 0) {
            CGPoint point = [gestureRecognizer locationOfTouch:0 inView:gestureRecognizer.view];
            CGFloat distX = abs(self.collectionView.lastTouchPos.x - point.x);
            CGFloat distY = abs(self.collectionView.lastTouchPos.y - point.y);
            if (distX > distY) {
                return NO;
            }
        } else {
            return NO;
        }
    }
    return YES;
}

只在上下滑动时使用 self.panGesture

更新

https://dev59.com/lGw05IYBdhLWcg3wqzms#8603839 看起来有一个更好的方法用于 gestureRecognizerShouldBegin

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if ([gestureRecognizer isEqual:self.panGesture]) {
        if (gestureRecognizer.numberOfTouches > 0) {
            CGPoint translation = [self.panGesture velocityInView:self.collectionView];
            return fabs(translation.y) > fabs(translation.x);
        } else {
            return NO;
        }
    }
    return YES;
}

1
适用于我的情况,除了我需要fabs(translation.y)< fabs(translation.x)。 - SeanR

4

如果你想使用平移手势,由于滚动视图使用了这些手势,我认为这将是困难的。但是,如果你能使用滑动手势,它很容易实现。

    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    swipe.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp;
    [self.scrollView addGestureRecognizer:swipe];

我测试过这个方法,可以成功调用处理程序,并且您不需要禁用滚动视图的平移手势识别器(在我的测试中,滚动视图足够高,内容足够短,没有垂直滚动 - 我不知道这是否是必要的)。


1
嘿,非常感谢你的帮助。这个方法完美地解决了我的问题,让我免去了为了让平移功能正常工作而更加疯狂的尝试。我一直避免使用滑动手势,因为我认为它不会对屏幕上缓慢拖动做出响应,但实际上即使是缓慢的滑动手势也能很好地工作。再次感谢。 - lramirez135
无用的。你自己试了滑动手势吗?它可定制性不够,无法适应。 - Vyachaslav Gerchicov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接