iOS UIScrollView clipToBounds = NO 未检测到子视图

Posted

技术标签:

【中文标题】iOS UIScrollView clipToBounds = NO 未检测到子视图【英文标题】:iOS UIScrollView clipToBounds = NO Subviews not detected 【发布时间】:2012-01-16 23:55:04 【问题描述】:

我有一个宽度/高度为 256x256 的滚动视图。我有在两个方向(左和右)拉伸的滚动视图的子视图。我将 clipToBounds 设置为 NO,以便可以在滚动视图中看到项目。

当用户触摸滚动视图支架中的空间(超出 256x256 的区域)时,我会检查 hittest 并返回滚动视图。

我的问题是我的滚动视图上的项目是按钮,如果按钮不在 256x256 内,则它不会接收到触摸事件。如何循环浏览滚动视图上的按钮,然后将事件转发到按钮?

我正在这样做Paging UIScrollView with peeking neighbor pages

但是我的滚动视图子视图没有收到事件。

在我看来,我已经尝试了以下所有应该发送事件的方法,而我的按钮将不会接收事件。事件链总是停在我的 UIScroll 视图 - 允许我滚动我的项目 - 但我如何将事件从滚动视图转发到按钮?

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
    if ([self pointInside:point withEvent:event]) 
        return self.scrollView;
    
    return nil;


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
    if ([self pointInside:point withEvent:event]) 
        return self.scrollView;
    
    return nil;


- (UIView *) hitTest:(CGPoint) point withEvent:(UIEvent *)event 
    UIView* child = nil;

    if ((child = [super hitTest:point withEvent:event]) == self) 
        return self.scrollView;
    
    return child;

【问题讨论】:

【参考方案1】:

这是答案和更好的解决方案。我们无需使用任意视图来转发事件,而是在 UIScrollView 中执行此操作,所有按钮和滑动都可以正常工作。

- (UIView )hitTest:(CGPoint)point withEvent:(UIEvent )event 
    UIView *view = [super hitTest:point withEvent:event];
    for (UIView *subview in self.subviews) 
        if (view != nil && view.userInteractionEnabled) 
            break;
        
        CGPoint newPoint = [self convertPoint:point toView:subview];
        view = [subview hitTest:newPoint withEvent:event];
    
    return view;

【讨论】:

我一直在尝试做同样的事情,这对我来说非常有效。谢谢。【参考方案2】:

你重写了 UIScrollView 的 hitTest 吗?

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

    UIView *contentView = [self.subviews count] ? [self.subviews objectAtIndex:0] : nil;
    return [contentView hitTest:pt withEvent:event];

【讨论】:

我的滚动视图自定义类中有这个确切的代码 - 但按钮永远不会收到事件。【参考方案3】:

请参阅 Matt Galloway 的教程 How To Use UIScrollView to Scroll and Zoom Content 中的检测滚动视图外的触摸部分 -

您使滚动视图小于屏幕并且未选中剪辑子视图:

并将其包装到容器视图中,将事件转发到滚动视图:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
    UIView *view = [super hitTest:point withEvent:event];
    if (view == self) 
        return _scrollView;
    
    return view;

【讨论】:

【参考方案4】:

您的滚动视图应该更大。 不会检测到主滚动视图框架之外的所有事件。 如果您需要向用户显示特定的背景区域,则将滚动视图的背景设置为透明,并在后面放置另一个视图。

【讨论】:

我将滚动视图设置为它的大小,因为我需要分页才能正常工作。如果我将滚动视图宽度扩展到全宽,那么它会分页全宽(而不是一个图标)。有没有办法以编程方式设置分页位置?

以上是关于iOS UIScrollView clipToBounds = NO 未检测到子视图的主要内容,如果未能解决你的问题,请参考以下文章

ios: uiscrollview 和 uiview 自动布局

iOS开发UI篇—UIScrollView控件实现图片缩放功能

ios UIScrollView

IOS - UIScrollView 边框和缩放

iOS 13 语音控制 UIScrollView

iOS开发UI篇—UIScrollView控件介绍