在 UIPanGestureRecognizer 和重新启用的 UIScrollView 之间连续滚动

Posted

技术标签:

【中文标题】在 UIPanGestureRecognizer 和重新启用的 UIScrollView 之间连续滚动【英文标题】:Continuous scrolling between UIPanGestureRecognizer and re-enabled UIScrollView 【发布时间】:2012-01-03 20:17:38 【问题描述】:

我有一个启用了分页的UIScrollView,并且我已经向其中添加了我自己的UIPanGestureRegonizer。在某些情况下,我的视图控制器将设置scrollview.scrollEnabled = NO,然后将平移手势识别器添加到其中(我没有使用滚动视图自己的识别器)。

因此,滚动已禁用,但我正在等待来自我的手势识别器的用户触摸。当它识别出来时,它会调用我重新启用滚动的操作。

问题是,当用户的手指仍然向下时,我的滚动视图没有用手指跟踪。在抬起手指然后再次拖动之前,它不会开始滚动。所以我的手势识别器正在吞下所有的触摸,而不是将任何触摸转发到滚动视图。

我尝试切换panGestureRecognizer.cancelsTouchesInView = NO;,但它似乎没有任何效果(我目前正在删除此识别器,一旦我重新启用滚动但我是否这样做并不能解决我的问题)。我还查看了 UIGestureRecognizerdelays... 属性,但它们似乎也没有帮助。

有什么想法吗?如何让这些事件继续转发到我的滚动视图?

【问题讨论】:

您是否尝试在gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 方法中返回YES @Hejazi 是的,我也实现了那个委托方法(并设置了我的委托),但是当手指仍然向下时它不会被调用(只有当我抬起并再次放下手指时这个委托方法是否被调用)。 【参考方案1】:

如果您只针对 ios 5 及更高版本,答案会简单一些,因为在这种情况下,您确实应该重用 UIScrollView panGestureRecognizer 属性。

无论如何,关键步骤是不要重用scrollEnabled,而是继承UIScrollView,创建你自己的属性来管理这个状态,并覆盖setContentOffset:。

    - (void) setContentOffset:(CGPoint)contentOffset
    
        if(self.programaticScrollEnabled)
            [super setContentOffset:contentOffset];
    

这是一种可能的 iOS 4+ 解决方案:

    子类 UIScrollView(或子类 UIScrollView 的另一个子类,具体取决于您的需要)。 覆盖所有初始化程序以确保调用您的设置代码。 声明 BOOL 属性并覆盖 setContentOffset: 如上所述。

    在您的设置代码中,设置 UIPanGestureRecognizer 并设置您的状态变量以允许程序化滚动(假设这是您想要的默认状态):

    panRecognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)] autorelease];
    //These properties may change according to your needs
    panRecognizer.cancelsTouchesInView = NO;
    panRecognizer.delaysTouchesBegan = NO;
    panRecognizer.delaysTouchesEnded = NO;
    [self addGestureRecognizer:panRecognizer];
    panRecognizer.delegate = self;
    
    self.programaticScrollEnabled = YES;
    

    管理哪些手势可以同时发生。就我而言:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
    
        return YES;
    
    

    在您需要的任何地方重新启用程序化滚动。例如:

    - (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
    
        self.programaticScrollEnabled = YES;
    
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    
        self.programaticScrollEnabled = YES;
        return YES;
    
    

【讨论】:

以上是关于在 UIPanGestureRecognizer 和重新启用的 UIScrollView 之间连续滚动的主要内容,如果未能解决你的问题,请参考以下文章

在 UILongPressGestureRecognizer 上启用 UIPanGestureRecognizer

UIPanGestureRecognizer 在视图中使用 UIScrollView

在播放 UIAnimation 时执行 UIPanGestureRecognizer

UIPanGestureRecognizer - ImageView 在平移后快速回到原始位置

UIPanGestureRecognizer 干扰滚动

UIPanGestureRecognizer 弹出 UIViewController