Answers:
您可以将控制器或视图(以创建手势识别器的任何视图)设置为的委托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
}
void
因此在运行时不会留下任何信息用于检测。但是您可以做的是沿视图层次结构前进,测试UIControl
,NO
如果找到任何控件,则返回。
作为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
}
基本上,这使所有用户输入类型的控件(例如按钮,滑块等)都可以工作
setCancelsTouchesInView = NO
与之交互以不触发与控件交互时的点击手势。但是,您可以写得更好:return ![touch.view isKindOfClass:[UIControl class]];
在这里找到此答案:链接
您也可以使用
tapRecognizer.cancelsTouchesInView = NO;
这阻止了抽头识别器成为捕获所有抽头的唯一方法
UPDATE - 迈克尔提到的链接描述这个属性的文档:cancelsTouchesInView
作为凯文·巴拉德(Kevin Ballard)回答的后续,我遇到了同样的问题,并最终使用了以下代码:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES;
}
它具有相同的效果,但是可以在任何视图深度的任何UIButton上使用(我的UIButton有几个视图深度,并且UIGestureRecognizer的委托没有对此的引用。)
在iOS 6.0及更高版本中,默认控制操作可防止手势识别器行为重叠。例如,按钮的默认操作是单击。如果您在按钮的父视图上附加了一个点击手势识别器,并且用户点击了该按钮,则按钮的操作方法将接收触摸事件而不是手势识别器。这仅适用于与控件的默认操作重叠的手势识别,该控件包括:.....
这些答案是不完整的。我必须阅读有关如何使用此布尔操作的多篇文章。
在您的* .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 ...");
}
从这里找到了另一种方法。它检测触摸是否在每个按钮内。
(1)pointInside:withEvent: (2) locationInView:
- (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]);
}
这是对我有用的 Swift版本的Lily Ballard的答案:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (scrollView.superview != nil) {
if ((touch.view?.isDescendantOfView(scrollView)) != nil) { return false }
}
return true
}
斯威夫特5
带手势的超级按钮
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let _ = touch.view as? UIButton { return false }
return true
}
以我为例,实施hitTest对我有用。我有按钮收藏视图
此方法通过调用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)
}
您可以通过设置以下布尔值来阻止UITapGestureRecognizer取消其他事件(例如,点击按钮):
[tapRecognizer setCancelsTouchesInView:NO];
您有一个简单的视图,并添加了一些UIButtons,UITextField控件作为该视图的子视图。现在,当您触摸视图上除控件(添加的子视图)以外的其他任何位置时,都想关闭键盘
将以下方法添加到XYZViewController.m(具有视图)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}