【问题标题】:Prevent touch events on subviews of scrolling UIScrollView in iOS7防止iOS7中滚动UIScrollView的子视图发生触摸事件
【发布时间】:2013-10-01 10:29:34
【问题描述】:

我在 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 更改?我希望我的应用在 iOS7 中的行为与 iOS6 相同。

【问题讨论】:

  • 这里与 UIScrollView 上的 UIButtons 相同。在 iOS6 中,您可以通过抓取按钮来滑动 UIScrollView,并且不会在按钮上调用 UIControlEventTouchDown。在 iOS7 UIControlEventTouchDown 将被调用。

标签: ios uiscrollview ios7 uicontrol


【解决方案1】:

不是很优雅,但在没有更好的想法的情况下,现在对我有用的是:

  • 在 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
}

【讨论】:

    【解决方案2】:

    这里与 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 处理程序,该处理程序可用于触摸逻辑。

    【讨论】:

      【解决方案3】:

      只需替换事件类型

      UIControlEventTouchDown 必须是 UIControlEventTouchUpInside

      【讨论】:

      • 其实,这太棒了!我正在寻找困难的解决方案,例如实施 hitTest 但这正是我需要的。 (虽然这并不是最初问题的真正答案)
      • 太好了,这就是我要找的:)
      【解决方案4】:

      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
      

      【讨论】:

      • 适用于 iPhone,但似乎不适用于 iPad
      猜你喜欢
      • 2011-09-15
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 2013-06-08
      • 2011-03-01
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多