在iOS7中,如何防止滚动UIScrollView的子视图响应触摸事件

9

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

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

iOS6和iOS7在以下操作时表现不同:
  1. 滑动UIScrollView开始滚动
  2. 点击UIScrollView停止滚动
在iOS6中,我的应用程序继续按预期运行:步骤#2的点击不会调用touchedDown - UIScrollView吞噬了触摸事件,因为它立即停止滚动。
但是在iOS7中,UIScrollView如预期停止滚动,而touchedDown 仍然被调用
是否有文档API更改?我希望我的应用程序在iOS7中与iOS6的行为完全相同。

1
在UIScrollView上使用UIButtons也有同样的问题。在iOS6中,您可以通过抓住按钮来滑动UIScrollView,并且UIControlEventTouchDown不会在按钮上被调用。但是在iOS7中,UIControlEventTouchDown将会被调用。 - hotdogsoup.nl
4个回答

9
@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

在 iPhone 上运行得很好,但似乎在 iPad 上不行。 - 0xWood

4

只需要更改事件类型

UIControlEventTouchDown 必须更改为 UIControlEventTouchUpInside


其实,这太棒了!我一直在寻找困难的解决方案,比如实现一个 hitTest,但这正是我所需要的。(虽然这并不是对最初问题的真正回答) - jeppeb
太好了,这正是我在寻找的 :) - LiangWang

3

虽然不太优雅,但是在没有更好的想法的情况下,这是我目前正在使用的方法:

  • 在 UIScrollView 上,将 canCancelContentTouches 设置为 YES,将 delaysContentTouches 设置为 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
}

0

在UIScrollView上使用UIButtons时,我也遇到了同样的问题。这是我的解决方案。

不再使用UIControlEventTouchDown事件:

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

我在我的内容UIViewController中实现了UIResponder touchesEnded方法:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// my scroll content touch logic
}

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

如果用户没有拖动UIscrollview,则会触发touchesEnded处理程序,可以用于触摸逻辑。


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