将滑动触按从UIView传递到基础UIScrollView以进行适当的滚动

将滑动触按从UIView传递到基础UIScrollView以进行适当的滚动,uiview,uiscrollview,overriding,swipe,touchesmoved,Uiview,Uiscrollview,Overriding,Swipe,Touchesmoved,我有一个类似于这两篇文章(和)的情况,为了最简洁地描述我的情况,我展示了这个文本/图形布局(类似于您在IB中看到的,用于强制缩进级别的点) UIView(主视图:320x460) . .UIScrollView(滚动视图:320x460) . .UIView(覆盖视图:320x40) . . . .UIButton(任意按钮1) . . . .UILabel(任意标签1) . . . .UILabel(任意标签2) 这里的目标是将OverlayView用作一个统一的透明容器,以便在ScrollV

我有一个类似于这两篇文章(和)的情况,为了最简洁地描述我的情况,我展示了这个文本/图形布局(类似于您在IB中看到的,用于强制缩进级别的点)

UIView(主视图:320x460)
. .UIScrollView(滚动视图:320x460)
. .UIView(覆盖视图:320x40)
. . . .UIButton(任意按钮1)
. . . .UILabel(任意标签1)
. . . .UILabel(任意标签2)

这里的目标是将OverlayView用作一个统一的透明容器,以便在ScrollView顶部定位和显示一些任意按钮/标签。这些按钮/标签应保持静止,而下方滚动视图中的内容应随用户滑动而移动。按钮/标签有时可能会同时隐藏/取消隐藏/缩放(带有动画),这使得在单个叠加视图中对它们进行分组非常方便

问题是,虽然点击覆盖图似乎正好传输到底层滚动视图,但切换动作没有效果。我可以通过覆盖

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
方法,但是我还没有找到一种方法来正确地将它们传递给ScrollView,使其滚动。显然,TouchsMoved方法不是UIScrollView用来检测/解释滑动的方法

我研究过的所有其他类似帖子要么找到了一个不同的解决方案,在我的案例中不起作用,要么就是没有解决。我还看到有人提到使用ToucheShouldBegin/ToucheShouldCancel,但我不知道这将如何实现。无论如何,我仍然希望社区中的一些见解能让我为这个问题提出一个优雅的解决方案——任何示例代码都会非常棒

提前谢谢你,乔尔


另外,我还应该提到,我需要使其与iOS 3.0兼容,因此我认为尝试使用UIGestureRecognitors是不可能的。

如何,在运行时在viewDidLoad中,将按钮从容器视图中取出,并将其直接作为子视图放置在视图中(并去掉容器视图)?然后,没有容器视图来拦截刷卡,但您仍然可以使用视图在IB中对内容进行分组

此外,您还可以将容器视图作为滚动视图的子视图放在滚动视图中,并在用户滚动时,在滚动视图委托中重新定位视图。这似乎很有可能让人紧张,但可能值得一试


另外,如果包含视图是一个可视容器,并且您需要查看它,则可以使用放置在CALayer顶部superview中的CALayer来渲染滚动视图,因为Calayer与输入无关,不会每次触摸。

您应该将UIScrollView子类化,并覆盖ToucheShouldCancelIncontentView:方法

-(BOOL)touchesShouldCancelInContentView:(UIView *)view
{

    if ([view isKindOfClass:[UIButton class]]) {//or whatever class you want to be able to scroll in
        return YES;
    }

    if ([view isKindOfClass:[UIControl class]]) {
        return NO;
    }

    return YES;
}

以下是一个对我很有效的简单解决方案:

在OverlayView(UIScrollView顶部的视图)中,将宽度和高度都设置为0(这样视图从技术上讲不再位于scrollview顶部),并设置clipsToBounds=no(这样OverlayView的内容仍然显示在scrollview顶部)。这对我来说很有魅力

 self.OverlayView.clipsToBounds = NO;
 CGRect frame = self.OverlayView.frame;
 self.OverlayView.frame = CGRectMake(frame.origin.x, frame.origin.y, 0, 0);

请注意,如果OverlayView包含交互式控件(如上面的按钮),则它们将不再工作。您需要将其移动到UIScrollView上方的它自己的视图中

我需要做一些类似的事情,在经过一些研究和阅读苹果的文档之后,我创建了这个非常简单和安全的开源库,它将解决你(MobileJoel)的问题。演示项目使用滚动视图,因此它直接关联:

因此,视图层次结构如下所示:

UIView (MainView: 320x460)    
. .UIScrollView (ScrollView: 320x460)
. .UIView (OverlayView: 320x40)  --> change this view to class NARootTouchThroughView in I.B.
. . . .UIView (transparent UIView that you change to class NATouchThroughView in I.B.)
. . . .UIButton (ArbitraryButton1)
. . . .UILabel (ArbitraryLabel1)
. . . .UILabel (ArbitraryLabel2)
UIView (MainView: 320x460)    
. .UIScrollView (ScrollView: 320x460)
. .NARootTouchThroughView (OverlayView: 320x40)
. . . .NATouchThroughView (transparent)
. . . .UIButton (ArbitraryButton1)
. . . .UILabel (ArbitraryLabel1)
. . . .UILabel (ArbitraryLabel2)
. . . .NATouchThroughView (transparent and covers the labels but not the UIButton)
因此,基本上,覆盖视图将转发其下方的触摸,然后由UIScrollview接收。如果您的UILabel很大,并且正在拦截触摸,则在其上方放置另一个NATouchThroughView,以便最终结果如下所示:

UIView (MainView: 320x460)    
. .UIScrollView (ScrollView: 320x460)
. .UIView (OverlayView: 320x40)  --> change this view to class NARootTouchThroughView in I.B.
. . . .UIView (transparent UIView that you change to class NATouchThroughView in I.B.)
. . . .UIButton (ArbitraryButton1)
. . . .UILabel (ArbitraryLabel1)
. . . .UILabel (ArbitraryLabel2)
UIView (MainView: 320x460)    
. .UIScrollView (ScrollView: 320x460)
. .NARootTouchThroughView (OverlayView: 320x40)
. . . .NATouchThroughView (transparent)
. . . .UIButton (ArbitraryButton1)
. . . .UILabel (ArbitraryLabel1)
. . . .UILabel (ArbitraryLabel2)
. . . .NATouchThroughView (transparent and covers the labels but not the UIButton)

我想你从来没有解决过这个问题?当然,canCancelContentTouches应该设置为YES(默认情况下是YES,但以防有人将其设置为NO)