防止子视图上的 UITapGestureRecognizer
Posted
技术标签:
【中文标题】防止子视图上的 UITapGestureRecognizer【英文标题】:Prevent UITapGestureRecognizer on Subview 【发布时间】:2013-07-14 01:18:52 【问题描述】:我不想在用户点击contentView
时调用closeShareView
,只在modalView
上调用,我该怎么做?
UIWindow* mainWindow = (((AppDelegate *)[UIApplication sharedApplication].delegate).window);
// Modal view
UIView *modalView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
modalView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8f];
// Content view (goes inside modalView)
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(modalView.center.x, modalView.center.y, 220, 220)];
[modalView addSubview:contentView];
[mainWindow addSubview:modalView];
// Tap gesture (added to modalView)
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeShareView:)];
gr.numberOfTapsRequired = 1;
[modalView addGestureRecognizer:gr];
【问题讨论】:
【参考方案1】:所以您想要“在内容视图之外单击以关闭模式”之类的交易?
不要将点击手势添加到整个模态视图,而是有一个背景视图来处理它,内容视图自然会拦截所有点击(如果它启用了用户交互),所以你基本上不必这样做任何编码。
UIWindow* mainWindow = (((AppDelegate *)[UIApplication sharedApplication].delegate).window);
// Modal view
UIView *modalView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Background tap view
UIView *backgroundView = [[UIView alloc] initWithFrame:modalView.bounds];
backgroundView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];
[modalView addSubview:backgroundView];
// Content view (goes inside modalView)
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(modalView.center.x, modalView.center.y, 220, 220)];
[modalView addSubview:contentView];
[mainWindow addSubview:modalView];
// Tap gesture (added to backgroundView)
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeShareView:)];
gr.numberOfTapsRequired = 1;
[backgroundView addGestureRecognizer:gr];
【讨论】:
模态视图是背景视图。即使启用了用户交互,子视图仍会识别点击。 模态视图不仅仅是背景视图,它是父视图,如果你在父视图中添加手势识别器,它会处理它,当然它不会工作所以,你可以在modalView
上添加另一个UIView
(或者UIControl
,如果你感觉超级懒惰),但在contentView
后面,这样就可以解决这个问题。
我实际上只是将代码复制并粘贴到一个新项目中,然后工作(这也让我感到惊讶:D)。
将 UIGestureRecognizer 切换到背景视图效果很好。很好的答案。【参考方案2】:
首先,在你的头文件中遵守UIGestureRecognizerDelegate
协议。
将UIGestureRecognizer
的委托设置为self
。
然后设置子视图的 标签 例如到 100(但你应该使用一个常数)。
然后使用类似的东西:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
CGPoint point = [gestureRecognizer locationInView:self.view];
UIView *viewTouched = [self.view hitTest:point withEvent:nil];
if (viewTouched.tag == 100)
// Don't BEGIN the gestureRecognizer
return NO;
else
// Do BEGIN the gestureRecognizer
return YES;
【讨论】:
【参考方案3】:我只是在检查被触摸的视图是否是自我,否则它是一个子视图并且手势不应该开始:
func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool
let point = gestureRecognizer.locationInView(self.view)
if let viewTouched = self.view.hitTest(point, withEvent: nil) where viewTouched != self.view
return false
else
return true
【讨论】:
【参考方案4】: @objc func handleTap(_ sender: UITapGestureRecognizer)
let point = sender.location(in: subview)
if !(tapView.frame.contains(point))
self.dismiss(animated: true, completion: nil)
这里,tapview 是添加点击手势的视图,subview 是它的子视图
【讨论】:
不适用于子视图下方的点击 - 它们未被识别为背景点击。【参考方案5】:我上面有一个backgroundView
和一个tableView
:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(backgroundTapped))
tapGestureRecognizer.delegate = self
backgroundView.addGestureRecognizer(tapGestureRecognizer)
// MARK: - UIGestureRecognizerDelegate
extension PhoneListViewController: UIGestureRecognizerDelegate
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool
let point = gestureRecognizer.location(in: self.tableView)
return !self.tableView.point(inside: point, with: nil)
【讨论】:
以上是关于防止子视图上的 UITapGestureRecognizer的主要内容,如果未能解决你的问题,请参考以下文章