具有UITapGestureRecognizer的视图中的UIButton

我的视图带有UITapGestureRecognizer。因此,当我点击视图时,另一个视图会出现在此视图上方。这个新视图有三个按钮。当我现在按下这些按钮中的一个时,我没有得到按钮动作,我只得到点击手势动作。所以我不能再使用这些按钮了。我该怎么做才能让事件通过这些按钮?奇怪的是,按钮仍然突出显示。

我无法在收到点击后删除UITapGestureRecognizer.因为有了它,新视图也可以被删除。意思是我想要一个行为类似于全屏视频控件

78599 次浏览

您可以将您的控制器或视图(创建手势识别器的那个)设置为UITapGestureRecognizer的代理。然后,在委托中,您可以实现-gestureRecognizer:shouldReceiveTouch:。在您的实现中,您可以测试触摸是否属于您的新子视图,如果是,则指示手势识别器忽略它。类似于以下内容:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if our control subview is on-screen
if (self.controlSubview.superview != nil) {
if ([touch.view isDescendantOfView:self.controlSubview]) {
// we touched our control surface
return NO; // ignore the touch
}
}
return YES; // handle the touch
}

作为Kevin Ballard回答的后续,我遇到了同样的问题,并最终使用了以下代码:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES;
}

它具有相同的效果,但这将适用于任何视图深度的任何UIButton(我的UIButton有几个视图深度,UIGestureRecognizer的委托没有对它的引用。)

在这里中找到了另一种方法。它检测触摸是否在每个按钮内。

(1)PointInside:WithEvent: (2)位置InView:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
// Don't recognize taps in the buttons
return (![self.button1 pointInside:[touch locationInView:self.button1] withEvent:nil] &&
![self.button2 pointInside:[touch locationInView:self.button2] withEvent:nil] &&
![self.button3 pointInside:[touch locationInView:self.button3] withEvent:nil]);
}

作为Casey对Kevin Ballard回答的跟进:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) {
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}

这基本上使所有用户输入类型的控件,如按钮,滑块等。工作

在这里找到了答案:链接

您还可以使用

tapRecognizer.cancelsTouchesInView = NO;

这防止敲击识别器成为捕捉所有敲击的唯一识别器。

更新-迈克尔提到了指向描述此属性的文档的链接:取消TouchesInView

您可以通过设置以下布尔值来阻止UITapGestureRecognizer取消其他事件(如点击按钮):

    [tapRecognizer setCancelsTouchesInView:NO];

如果你的场景是这样的:

你有一个简单的视图和一些UIButton,UITextField控件作为子视图添加到该视图中。现在,您希望在触摸视图上除控件(您添加的子视图)以外的任何其他位置时关闭键盘。

那么解决方案是:

将以下方法添加到您的XYZViewController.m(它具有您的视图)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}

这些答案不完整。关于如何使用这个布尔运算,我不得不阅读多个帖子。

在*.H文件中,添加以下内容

@interface v1ViewController : UIViewController <UIGestureRecognizerDelegate>

在你的*.m文件中添加这个

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {


NSLog(@"went here ...");


if ([touch.view isKindOfClass:[UIControl class]])
{
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.






//tap gestrure
UITapGestureRecognizer *tapGestRecog = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTappedOnce)];
[tapGestRecog setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:tapGestRecog];




// This line is very important. if You don't add it then your boolean operation will never get called
tapGestRecog.delegate = self;


}




-(IBAction) screenTappedOnce
{
NSLog(@"screenTappedOnce ...");


}

在IOS 6.0及更高版本中,默认控制操作可防止重叠手势识别器行为。例如,按钮的默认操作是单击。如果按钮的父视图附加了一个单击手势识别器,并且用户单击了该按钮,则该按钮的操作方法将接收触摸事件,而不是手势识别器。这仅适用于与控件的默认操作重叠的手势识别,包括:..

来自苹果的API文档

优化cdasher的答案,你得到

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
return ![touch.view isKindOfClass:[UIControl class]];
}

以下是适用于我的莉莉·巴拉德的回答的SWIFT版本:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (scrollView.superview != nil) {
if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
}
return true
}

斯威夫特5

使用TapGesture的SuperView上的按钮

 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let _ = touch.view as? UIButton { return false }
return true
}

在我的案例中,实施希特斯特对我有用。我有带按钮的收藏视图

该方法通过调用每个子视图的point(inside:with:)方法来遍历视图层次结构,以确定哪个子视图应该接收触摸事件。如果point(inside:with:)返回TRUE,则以类似的方式遍历子视图的层次结构,直到找到包含指定点的最前面的视图。

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled else { return nil }


guard !isHidden else { return nil }


guard alpha >= 0.01 else { return nil }


guard self.point(inside: point, with: event) else { return nil }


for eachImageCell in collectionView.visibleCells {
for eachImageButton in eachImageCell.subviews {
if let crossButton = eachImageButton as? UIButton {
if crossButton.point(inside: convert(point, to: crossButton), with: event) {
return crossButton
}
}
}
}
return super.hitTest(point, with: event)
}