防止在 iOS7 中滚动 UIScrollView 的子视图上发生触摸事件



我在UIScrollView中有一个UIControl。在我的UIControl init中,我安装了一些触摸事件处理程序,例如

[self addTarget:_delegate
         action:@selector(touchedDown) forControlEvents:UIControlEventTouchDown];

当我执行以下操作时,iOS6 和 iOS7 的行为不同:

  1. 滑动 UIScrollView 以开始滚动
  2. 点击 UIScrollView 以停止滚动

在 iOS6 中,我的应用程序继续按预期运行:步骤 #2 中的点击不会调用touchedDown - UIScrollView 会立即停止滚动时吞下触摸事件。

但在 iOS7 中,UIScrollView 会按预期停止滚动,而 touchedDown 仍被调用

是否有记录在案的 API 更改?我希望我的应用程序的行为与 iOS6 中的 iOS7 相同。

适用于

iOS 7 的解决方法

@interface UIScrollViewFixed : UIScrollView
@end
@implementation UIScrollViewFixed
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (self.isDragging || self.isDecelerating) {
        return self;
    }
    return [super hitTest:point withEvent:event];
}
@end

只需替换事件类型

UIControlEventTouchDown必须UIControlEventTouchUpInside

不是很优雅,但在没有任何更好的想法的情况下,这就是现在对我有用的东西:

  • 在 UIScrollView 上,将canCancelContentTouches设置为 YESdelaysContentTouches设置为 NO
  • 在 UIScrollViewDelegate 中,在 UIScrollView 滚动时切换 UIScrollView 的子视图的 userInteractionEnabled 属性:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [_contentView setUserInteractionEnabled:NO];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [_contentView setUserInteractionEnabled:YES];
    }
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [_contentView setUserInteractionEnabled:YES];
}
  • 子类化 UIScrollView 并实现:
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
    return YES;
}
  • 子类化 UIControl 并实现 touchesCancelled:withEvent 以反转UIControlEventTouchDown处理程序执行的任何操作:
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    //custom logic
}

UIScrollView 上的 UIButtons 也是如此。这是我现在的解决方案。

而不是使用内容 UIControlEventTouchDown 事件:

[button addTarget:_delegate
         action:@selector(touchedDown) forControlEvents:UIControlEventTouchDown];

我在我的内容UIViewController中实现了UIResponder touchesEnd方法:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// my scroll content touch logic
}

如果用户触摸内容并开始拖动触摸,则不会调用已结束处理程序。UIResponder touchesCanceled 方法将。

如果用户不拖动 UIscrollview,则会触发 touchesEnd 处理程序,该处理程序可用于触摸逻辑。

最新更新