手势识别器和按钮操作
我有一个看起来像这样的视图层次结构:
UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel
我已将手势识别器附加到我的 UIView (B)。我面临的问题是,我没有对 UIView (B) 内的圆角矩形按钮执行任何操作。 singleTap 手势识别器捕获/覆盖按钮的 Touch Up Inside 事件。
我怎样才能让它发挥作用?我认为响应者链层次结构将确保按钮触摸事件被优先考虑,并且它将被触发!我缺少什么?
这是一些相关代码:
#pragma mark -
#pragma mark View lifecycle (Gesture recognizer setup)
- (void)viewDidLoad {
[super viewDidLoad];
// double tap gesture recognizer
UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)];
dtapGestureRecognize.delegate = self;
dtapGestureRecognize.numberOfTapsRequired = 2;
[self.viewB addGestureRecognizer:dtapGestureRecognize];
// single tap gesture recognizer
UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
tapGestureRecognize.delegate = self;
tapGestureRecognize.numberOfTapsRequired = 1;
[tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize];
[self.viewB addGestureRecognizer:tapGestureRecognize];
// add gesture recodgnizer to the grid view to start the edit mode
UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)];
pahGestureRecognizer.delegate = self;
pahGestureRecognizer.minimumPressDuration = 0.5;
[self.viewB addGestureRecognizer:pahGestureRecognizer];
[dtapGestureRecognize release];
[tapGestureRecognize release];
[pahGestureRecognizer release];
}
#pragma mark -
#pragma mark Button actions
- (IBAction)buttonTouchUpInside:(id)sender {
NSLog(@"%s, %@", __FUNCTION__, sender);
}
#pragma mark -
#pragma mark Gesture recognizer actions
- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"%s", __FUNCTION__);
}
- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"%s", __FUNCTION__);
}
- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded: {
NSLog(@"%s", __FUNCTION__);
break;
}
default:
break;
}
}
I have a view hierarchy that looks something like this:
UIView (A)
UIView > UIImageView
UIView > UIView (B)
UIView > UIView (B) > Rounded Rect Button
UIView > UIView (B) > UIImageView
UIView > UIView (B) > UILabel
I've attached gesture recognizer(s) to my UIView (B). The problem that i'm facing is that i don't get any actions for the Rounded Rect Button which is inside the UIView (B). The singleTap gesture recognizer captures/overrides the button's Touch Up Inside event.
How can i make it work? I thought that the responder chain hierarchy will make sure that the button touch event will be given preference, and it WILL get triggered! What am i missing?
Here's some related code:
#pragma mark -
#pragma mark View lifecycle (Gesture recognizer setup)
- (void)viewDidLoad {
[super viewDidLoad];
// double tap gesture recognizer
UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)];
dtapGestureRecognize.delegate = self;
dtapGestureRecognize.numberOfTapsRequired = 2;
[self.viewB addGestureRecognizer:dtapGestureRecognize];
// single tap gesture recognizer
UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)];
tapGestureRecognize.delegate = self;
tapGestureRecognize.numberOfTapsRequired = 1;
[tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize];
[self.viewB addGestureRecognizer:tapGestureRecognize];
// add gesture recodgnizer to the grid view to start the edit mode
UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)];
pahGestureRecognizer.delegate = self;
pahGestureRecognizer.minimumPressDuration = 0.5;
[self.viewB addGestureRecognizer:pahGestureRecognizer];
[dtapGestureRecognize release];
[tapGestureRecognize release];
[pahGestureRecognizer release];
}
#pragma mark -
#pragma mark Button actions
- (IBAction)buttonTouchUpInside:(id)sender {
NSLog(@"%s, %@", __FUNCTION__, sender);
}
#pragma mark -
#pragma mark Gesture recognizer actions
- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"%s", __FUNCTION__);
}
- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"%s", __FUNCTION__);
}
- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded: {
NSLog(@"%s", __FUNCTION__);
break;
}
default:
break;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
在“shouldReceiveTouch”方法中,您应该添加一个条件,如果触摸位于按钮中,则返回 NO。
这是来自苹果 SimpleGestureRecognizers 示例。
希望它会有所帮助
编辑
正如 Daniel 指出的,您必须遵守
UIGestureRecognizerDelegate
才能正常工作。沙尼
In the "shouldReceiveTouch" method you should add a condition that will return NO if the touch is in the button.
This is from apple SimpleGestureRecognizers example.
hope it will help
Edit
As Daniel noted you must conform to
UIGestureRecognizerDelegate
for it to work.shani
我也遇到了同样的问题,然后我尝试了
它现在工作正常..............
I also had the same problem , then i tried with
It is working now perfectly.........
一般来说,我们使用下面的委托方法来避免各种UIControls中的触摸:
注意:不要对gestureRecognizerShouldBegin进行此检查(检查recognizer.view类类型),它不会起作用。
Generally speaking, we use below delegate method to avoid the touch in all kinds of UIControls:
Note: DO NOT do this check (check the recognizer.view class type) the gestureRecognizerShouldBegin, it won't work.
这是一个 Swift 3.0 版本:
不要忘记:
让你的 Tapper 对象委托给 self(例如:tapper.delegate = self)
Here is a Swift 3.0 version:
Don't forget to:
Make your tapper object delegate to self (e.g: tapper.delegate = self)
在我看来,最好的解决方案是使用下面的代码片段:
The best solution is to my mind using code snippet below:
这是一个 Swift 版本:
不要忘记:
UIGestureRecognizerDelegate
tapper.delegate = self
)Here is a Swift version:
Don't forget to:
UIGestureRecognizerDelegate
tapper.delegate = self
)对于委托内的 Swift 5,您只需添加:
for Swift 5 inside the delegate you can just add:
Vivienne 答案的 Swift 版本:
Swift version of Vivienne answer:
我的情况如下:
上部 UIView 上的 tapGesture 导致与 UIControl 目标发生冲突。如果目标是使用
touchDown
设置的(但未调用touchUpInside
),或者如果我将继承从UIControl
更改为 < code>UIButton,同时保持事件touchUpInside
上的目标设置。我要做的就是解决这个问题:
上视图被设置为其点击手势的代表。
函数 funcgestureRecognizer(_gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool 的实现(在上层 UIView 中)如下所示:
通过实现该委托函数,我现在可以将 UIControl 和目标设置保留在
touchUpInside
上! :)My case was the following :
The tapGesture on the upper UIView was causing a conflict with the UIControl target. The target was called if the target was setup with
touchDown
(but not called fortouchUpInside
) or if I was changing the inheritance fromUIControl
toUIButton
while keeping the target setup on eventtouchUpInside
.What I do to solve that is :
upper view is setup as delegate of its tap gesture.
Function
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
is implemented (in upper UIView) like that :With that delegate function implemented I'm now able to keep my UIControl and the target setup on
touchUpInside
! :)