如何阻止从超级视图到子视图的手势?
Posted
技术标签:
【中文标题】如何阻止从超级视图到子视图的手势?【英文标题】:How to block a gesture from superview to subview? 【发布时间】:2013-06-07 08:37:32 【问题描述】:我正在编写一个模块,每次在视图上滑动时,都会添加两个视图大小为一半的子视图。这些子视图有自己的手势(例如:平移,...)。我第一次刷,没关系,因为没有创建任何子视图。但是一旦创建了子视图,每次我滑动时,滑动手势总是传递给它的子视图。 :(,所以我必须滑动2次才能划分。
我想知道有没有办法阻止滑动传递到它的子视图?谢谢。
更新 我使用 shouldRecognizeSimultaneouslyWithGestureRecognizer 使这些手势同时工作。但是还是有一些问题。父视图有它的滑动手势,子视图有它的平移手势。由于我使用了 souldRecognizeSimultaneouslyWithGestureRecognizer,所以有时在我平移时,会触发滑动手势。那么,您知道在这种情况下如何在 Pan 处于活动状态时禁用 Swipe 吗?
【问题讨论】:
你想要什么行为?如果子视图和父视图中都有手势识别器,显然存在冲突。 我只希望在父视图中滑动行为,而不是子视图。我没有将此手势添加到子视图中。 【参考方案1】:你必须实现 UIGestureRecognizerDelegate 方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
并将您的控制器添加为手势识别器的代表。然后,当两个手势识别器响应一个手势时,将调用此方法,您可以在此处为您的应用实现所需的逻辑。
在控制器的接口声明中你必须输入:
@interface testcViewController () <UIGestureRecognizerDelegate>
那么,在创建手势识别器时:
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
swipe.direction = UISwipeGestureRecognizerDirectionDown;
swipe.delegate = self;
[self.view addGestureRecognizer:swipe];
然后,最后,将此方法添加到控制器:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
BOOL shouldInteract = NO;
//Here you decide whether or not the two recognizers whould interact.
return shouldInteract;
编辑 你也可以实现
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
在这里,检测您是否已经呈现了子视图,并阻止您想要的任何手势。
【讨论】:
【参考方案2】:为了阻止来自超级视图的所有手势识别器,我创建了一个 UIGestureRecognizer 子类,它在附加到视图时会执行此操作。请参阅以下代码(取自我的 WEPopover 项目):
#import "WEBlockingGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
@implementation WEBlockingGestureRecognizer
- (id)init
return [self initWithTarget:self action:@selector(__dummyAction)];
- (id)initWithTarget:(id)target action:(SEL)action
if ((self = [super initWithTarget:target action:action]))
self.cancelsTouchesInView = NO;
return self;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
if (self.state == UIGestureRecognizerStatePossible)
self.state = UIGestureRecognizerStateBegan;
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
self.state = UIGestureRecognizerStateRecognized;
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
return [self isGestureRecognizerAllowed:preventingGestureRecognizer];
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
return ![self isGestureRecognizerAllowed:preventedGestureRecognizer];
- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
return ![self isGestureRecognizerAllowed:otherGestureRecognizer];
- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
return NO;
- (BOOL)isGestureRecognizerAllowed:(UIGestureRecognizer *)gr
return [gr.view isDescendantOfView:self.view];
- (void)__dummyAction
@end
如果您想阻止附加到某个视图的父视图的所有手势识别器,只需执行以下操作:
- (void)blockParentGesturesForView:(UIView *)v
[v addGestureRecognizer:[WEBlockingGestureRecognizer new]];
【讨论】:
好主意,这让手势看起来像事件链,子视图会阻止超级视图手势。【参考方案3】:将 userinteractionEnabled 设置为子视图的 NO
subview.userinteractionEnabled=NO
如果您不想禁用 userInteraction,请使用cancelsTouchesInView
方法
cancelsTouchesInView——如果手势识别器识别出它的手势, 它会从他们的视野中解除该手势的剩余触摸(所以 窗口不会提供它们)。窗口取消之前的 使用 (touchesCancelled:withEvent:) 消息传递触摸。如果一个 手势识别器无法识别其手势,视图接收到 多点触摸序列中的所有触摸。
【讨论】:
所以它也会禁用子视图手势。我不想那样。我希望子视图可以交互。 子视图也有手势识别器,因此必须启用用户交互。【参考方案4】:试试这样,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
return NO;
【讨论】:
【参考方案5】:考虑到我有一个dialogView
作为我的UIViewController
的主要view
的直接子视图,我将手势识别器附加到主要view
并执行以下操作(将我的视图控制器设置为手势识别器delegate)
:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
let point = touch.location(in: view)
return !dialogView.frame.contains(point)
【讨论】:
【参考方案6】:采用我在这里阅读的内容并制作了一个非常棒的 Swift 5(对我来说)!我在一个视图中有一个滑动控件,该控件也有一个用于移动到另一个视图的滑动识别器。如果手指没有碰到滑块的拇指,则整个视图都会移动。
通过将此视图放置在滑块下方(已展开使其更大一些),未命中不会有任何作用。
final class BlockingView: UIView, UIGestureRecognizerDelegate
let swipe: UISwipeGestureRecognizer = UISwipeGestureRecognizer();
init()
super.init(frame: CGRect.zero)
swipe.direction = [.left, .right]
self.addGestureRecognizer(swipe)
required init?(coder: NSCoder) fatalError("init(coder:) has not been implemented")
@objc override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool return false
希望这可以为某人省去麻烦!
【讨论】:
以上是关于如何阻止从超级视图到子视图的手势?的主要内容,如果未能解决你的问题,请参考以下文章