检测 UIScrollView 之外的点击

Posted

技术标签:

【中文标题】检测 UIScrollView 之外的点击【英文标题】:Detecting clicks outside of UIScrollView 【发布时间】:2011-10-21 11:48:02 【问题描述】:

我已经根据这种技术实现了分页滚动 (ios develop. How to extend UIScrollView's scroll event responding area?) 并且它按预期工作。

我正在滚动的视图包含几个按钮,我希望不仅能够单击居中/分页进入滚动视图的按钮,还能够单击其左侧和右侧的按钮。我找不到任何方法来解决这个问题,但我还不是真正的 iOS 绝地武士,但希望你们中的一个是 :)

从屏幕上可以看出,UIScrollView 大约是窗口宽度的三分之一,UIScrollView 的内容大小要大得多:大约 1500 像素,并且包含许多以编程方式添加的按钮。这个解决方案最酷的地方,也是真正起作用的部分,是按钮: 1) 被分页到滚动视图中 2)在滚动视图之外可见(因为未选中滚动视图的“剪辑子视图”)3)按钮在uiscrollview内部可见时是可点击的。

但不起作用的只是: - 当前位于窗口外的按钮在单击它们时不会收到“他们的”点击,而是将事件转发到底层(窗口的白色部分)视图。

【问题讨论】:

只是为了确保我正确理解您的问题,您是说您希望能够从滚动视图边界和框架之外获得点击? 迈克尔:是的,我相信这就是我想要的。目标是使滚动视图中的组件(但不在其分页区域中)可单击。很抱歉我不擅长解释自己。 可能值得包含一个屏幕截图。如果您在滚动视图之外有按钮,但仍属于同一个 xib 文件的一部分,则可以在单击这些按钮时分配要触发的操作。 Michael:按钮是以编程方式添加到 UIScrollView 而不是在笔尖中,即使这样,问题是事件永远不会到达显示在 uiscrollview 之外的按钮。 感谢您提供该屏幕截图!啊,所以你的意思是按钮被添加到 UIScrollView 的 contentView 但在 UIScrollView 的可见矩形(和边界)之外? 【参考方案1】:

所以,

我终于设法解决了这个难题,解决方案分为两个 部分。问题是,正如您所记得的那样,点击事件并没有传播到 在 UIScrollView 之外(可见)的按钮。事实证明,点击是由底层视图捕获的,并且可以通过稍微改变关于谁被击中的规则来操纵他们找到目标的方式,从而欺骗事件在你想要的地方传递。不确定这是否是应该完成的,但它解决了我的问题...... :)

1) 第一个必须覆盖底部视图中的以下方法 以便它在适当的时候返回滚动视图而不是自身。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

    UIView *view = [super hitTest:point withEvent:event];

    if (view == self) 
        return [self scrollView];

    return view;

2) scrollView 必须重写两个方法以将点击移交给其包含的对象。

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
    
       UIView *view = [super hitTest:point withEvent:event];
       // Always return us.
       return view ;    
     

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

    // We want EVERYTHING!
    return YES;

非常感谢各位 cmets 并愿意提供帮助。 呵呵

【讨论】:

非常感谢!但是有一个小问题......所有超出超级视图边界的子视图都有较浅的颜色。稍微轻一点...可以轻松修复吗?【参考方案2】:

受@tommys 提到的答案的启发,事实证明,通过覆盖 UIView 的 hinTest 方法并返回 scrollView,您实际上可以将此 UIView 的滑动分离到 scrollView。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

    UIView *view = [super hitTest:point withEvent:event];

    // Doing this make you detached the swiping to the scrollView
    if (view == self) 
        return [self scrollView];

    return view;

所以这个UIView就像是scrollView的一个扩展滚动区域,想法就在这里。如果您在 scrollView 上制作 UIView 掩码并且窗口大小相同,则在窗口内的任意位置滑动会使 scrollView 滚动。

这是一个例子,ExtensionScrollArea

【讨论】:

【参考方案3】:

这是我的版本:

    在容器中命中测试

    - (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event
    
        if ( CGRectContainsPoint( self.frame, point ) && ! self.hidden ) // <-- *
        
            if ( ! CGRectContainsPoint( scrollView.frame, point ) )
                return scrollView;
        
        return [super hitTest:point withEvent:event];
    
    

(*) 如果您正在移动或隐藏您的视图,例如,如果您有多个视图,每个视图都有自己的滚动视图,则此标记线很重要。如果你没有这条线,你可能会将所有的触摸都指向屏幕外的滚动视图!

    在滚动视图中覆盖

    - (BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event
    
        return YES;
    
    

(在容器的 hitTest 中,您可以在 if 语句中排除额外的帧以获得默认行为):)

【讨论】:

以上是关于检测 UIScrollView 之外的点击的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 内的可选 UITableViewCells

UIScrollView 检测点击

swift3.0 点击UIScrollView中输入框之外的区域关闭键盘

检测对 UIScrollView 内的 UIImageView 的点击

UIScrollView 帮助

IOS 管理键盘 - 上移 UIScrollView 内容