VC 容器中 UINavigationController 的点击区域问题 [英] Tap region issues with UINavigationController in VC containment

查看:15
本文介绍了VC 容器中 UINavigationController 的点击区域问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 iOS 应用,我在其中添加了一个 UINavigationController 作为主屏幕的子视图控制器.它是垂直排列的,因此导航控制器占据主视图高度的底部并且是全宽的.有一个按钮(实际上是一个带有点击识别器的自定义视图)位于导航的正上方,用于隐藏和显示它;隐藏导航时,按钮位于主屏幕底部,显示导航时,按钮位于导航栏顶部的正上方.

I have an iOS app in which I add a UINavigationController as a child view controller to the main screen. It's arranged vertically, so that the nav controller takes up a bottom part of the main view's height and is full-width. There is a button (actually a custom view with a tap recognizer) that sits right above the nav that is used to hide and show it; when the nav is hidden, the button is at the bottom of the main screen, and when the nav is shown the button is right above the top of the nav bar.

问题在于导航栏似乎拦截了按钮底部 10 点左右的触摸.这是为什么?

The issue is that the navigation bar appears to intercept touches on the bottom 10 points or so of the button. Why is this?

添加孩子的代码如下所示:

The code to add the child looks like this:

UIViewController *root = [[[UIViewController alloc]init]autorelease]; //some VC
UINavigationController *nav = [[[UINavigationController alloc]initWithRootViewController:root]autorelease];
[self addChildViewController:nav];
CGRect rect = self.view.frame;
CGFloat height = 500;
nav.view.frame = CGRectMake(0, rect.size.height - height, rect.size.width, height);
[self.view addSubview:nav.view];
[nav didMoveToParentViewController:self];

//Now the button
UIView *view = [[[UIView alloc]initWithFrame:CGRectZero]autorelease];
view.backgroundColor = [UIColor greenColor];
[self.view addSubview:view];
view.frame = CGRectMake(0, rect.size.height - 500 - 40, rect.size.width, 40);
UITapGestureRecognizer *recog = [[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onToggleSplit)]autorelease];
[view addGestureRecognizer:recog];

onToggleSplit 向上和向下动画导航.当它启动时,点击按钮"的底部 10 个点左右什么都不做.我尝试在我的自定义按钮"视图上覆盖 touchesBegan,但它甚至没有被调用.

onToggleSplit animates the nav up and down. When it's up, taps on the bottom 10 points or so of the "button" do nothing. I tried overriding touchesBegan on my custom "button" view, and that doesn't even get called.

如果我为子 VC 使用常规的 UIViewController(或其子类),按钮会按预期响应.

If I use a regular UIViewController (or a subclass thereof) for the child VC, the button responds as expected.

推荐答案

此问题已被问及回答 此处.基本上,iOS 上的控件具有倾斜区域",旨在允许用户进行草率的触摸准确性.我将提交一个关于这不应该超出控件视图控制器边界的错误.

This has been asked and answered here. Basically, controls on iOS have "slop zones" designed to allow sloppy touch accuracy on the part of the user. I'm going to file a bug about how this shouldn't reach outside the control's view controller's bounds.

更新:作为雷达 19504573 提交.

Update: filed as radar 19504573.

更新 2:我的雷达被标记为 8088542 的副本,这是打开的.此外,我的案例有点简单(导航栏顶部的一个视图),所以我能够克服这个问题.我覆盖了 hitTest:withEvent: 并注意到当点击发生时,它会被调用两次.首先,触摸坐标是你期望的,调用 super 返回你期望的视图.第二个事件具有相同的 timestamp 值,但 y 坐标更高(在屏幕上更低)并且 super 返回导航栏.所以:

Update 2: my radar has been marked as a duplicate of 8088542, which is open. Also, my case is somewhat simple (one view right on top of a navigation bar), so I was able to overcome the issue. I overrode hitTest:withEvent: and noticed that when a tap happens, it gets called twice. On the first, the touch coordinates are what you expect, and calling super returns the view you expect. The second has the same timestamp value on the event, but the y coordinate is higher (lower on the screen) and super returns the nav bar. So:

  • 子类 UIView 并添加属性 viewToWatch.
  • 在我的主视图控制器的笔尖/故事板中,将视图类设置为我的子视图.
  • 在我的主视图控制器的 viewDidLoad 中,抓取视图,将其投射,并将其 viewToWatch 设置为正在窃取触摸事件的视图.
  • 在自定义视图中,定义两个私有属性:NSTimeInterval lastTimestampBOOL isInView.
  • 覆盖 hitTest:withEvent:.如果调用 super 产生 viewToWatch,请将 lastTimestamp 设置为事件的标记,并将 isInView 设置为 YES.否则,如果 super 返回导航栏,如果事件的标记匹配并且 isInView 仍然是 YES,则重置两个属性并返回 viewToWatch.
  • Subclass UIView and add a property viewToWatch.
  • In my main view controller's nib/storyboard, set the view class to my subview.
  • In my main view controller's viewDidLoad, grab the view, cast it, and set its viewToWatch to the view whose touch events are being filched.
  • In the custom view, define two private properties: NSTimeInterval lastTimestamp and BOOL isInView.
  • Override hitTest:withEvent:. If calling super yields viewToWatch, set the lastTimestamp to the event's stamp and isInView to YES. Otherwise, if super returns a nav bar, if the event's stamp matches and isInView is still YES, reset both properties and return viewToWatch.

到目前为止一切正常.

这篇关于VC 容器中 UINavigationController 的点击区域问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆