【问题标题】:Passing swipe touches from UIView to underlying UIScrollView for proper scrolling将滑动触摸从 UIView 传递到底层 UIScrollView 以进行正确滚动
【发布时间】:2011-03-03 21:00:01
【问题描述】:

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

UIView(主视图:320x460)
. .UIScrollView (ScrollView: 320x460)
. .UIView (OverlayView: 320x40)
. . . .UIButton (ArbitraryButton1)
. . . .UILabel (ArbitraryLabel1)
. . . .UILabel (ArbitraryLabel2)

这里的目标是让 OverlayView 作为一个统一的、透明的容器来定位和显示一些任意按钮/标签在 ScrollView 的顶部。这些按钮/标签应保持静止,而下方 ScrollView 中的内容会随着用户滑动而移动。按钮/标签有时可能会同时隐藏/取消隐藏/缩放(与动画一起),这使得将它们全部分组在单个 OverlayView 中很方便。

问题在于,虽然在 OverlayView 上的点击似乎可以很好地直接传递到底层 ScrollView,但滑动动作没有效果。我可以通过覆盖来检测/拦截滑动

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

OverlayView 中的方法,但是我还没有找到一种方法以使其滚动的方式正确地将它们传递给 ScrollView。显然 touchesMoved 方法不是 UIScrollView 用来检测/解释滑动的方法?

我研究过的所有其他类似帖子要么找到了在我的情况下不起作用的不同解决方案,要么只是没有解决。我还看到提到使用 touchesShouldBegin / touchesShouldCancel 虽然我不知道如何实现。无论如何,仍然希望社区有一些见解可以让我为此提出一个优雅的解决方案 - 任何示例代码都会很棒。

提前致谢,乔尔。

附: - 我还应该提到,我需要使它与 iOS 3.0 兼容,所以我认为尝试使用 UIGestureRecognizers 已经过时了。

【问题讨论】:

  • 我想你从来没有解决过这个问题?

标签: uiview uiscrollview overriding swipe touchesmoved


【解决方案1】:

这里有一个对我很有效的更简单的解决方案:

在 OverlayView(UIScrollView 顶部的视图)中,将宽高都设为 0(这样视图在技术上不再位于滚动视图顶部)并设置 clipsToBounds = NO(这样 OverlayView 的内容仍然显示在滚动视图的顶部)。它对我来说就像一个魅力。

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

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

【讨论】:

    【解决方案2】:

    如何在运行时 viewDidLoad 中将按钮从容器视图中取出并将它们作为子视图直接放置在视图中(并摆脱容器视图)?然后没有容器视图来拦截滑动,但您仍然可以使用视图对 IB 中的内容进行分组。

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

    此外,如果包含视图是可视化容器并且您需要查看它,则可以改为使用放置在 CALayer 顶部的超级视图中的 CALayer 来呈现滚动视图,因为 CALayer 与输入无关并且不会每个都碰。

    【讨论】:

      【解决方案3】:

      你应该继承 UIScrollView 并覆盖 touchesShouldCancelInContentView: 方法

      -(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;
      }
      

      【讨论】:

      • 当然,canCancelContentTouches 应该设置为 YES(默认为 YES,但以防万一有人将其设置为 NO)
      【解决方案4】:

      我需要类似的东西,经过一些研究和阅读 Apple 的文档后,我创建了这个非常简单且安全的开源库,可以解决您的 (MobileJoel) 问题。演示项目使用滚动视图,因此直接关联:
      https://github.com/natrosoft/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)
      

      所以基本上你的覆盖视图会转发它下面的触摸,然后被 UIScrollview 接收。如果您的 UILabel 很大并且正在拦截触摸,则在它​​们之上放置另一个 NATouchThroughView,以便最终结果如下所示:

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-21
        • 2014-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-08
        • 2013-11-09
        相关资源
        最近更新 更多