将UIGesture转发到后面的视图
我正在iphone(iOS 4.0或更高版本)的应用程序,并在多个视图之间的触摸处理有一些麻烦。 我有这样的视图结构
---> A superView | ---> SubView - A | ---> SubView - B (exactly on top of A, completely blocking A).
基本上我有一个superView,并且兄弟姐妹子视图A和B.B具有与A相同的框架,因此完全隐藏A.
现在我的要求是这样的。
- 子视图B应该接收所有轻扫和轻击(单和双)手势。
- 子视图A应该收到所有捏手势。
这是我如何添加手势识别器的意见
UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)]; [leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)]; leftSwipe.delegate = self; [bView addGestureRecognizer:leftSwipe]; [leftSwipe release]; UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)]; [rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)]; rightSwipe.delegate = self; [bView addGestureRecognizer:rightSwipe]; [rightSwipe release]; UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)]; pinch.delegate = self; [aView addGestureRecognizer:pinch]; [pinch release];
我做了一些研究,对我来说UIGestureRecognizerDelegate
看起来很有希望,我实现了委托方法
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
我为SubView B返回NO,希望底层视图将得到这些事件。 没有这样的运气,但
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] && [gestureRecognizer view] == bView) { NSLog(@"pinchGesture"); //bView.userInteractionEnabled = NO; return NO; } return YES; }
然后,我禁用了SubView B在代表callback中的用户交互(在上面的代码块中的注释代码),当捏手势被识别时,希望剩下的部分手势将被SubView A接收。
所以这就是我现在的立场。 我已经看到了这个问题,接受的答案涉及属性cancelsTouchesInView
。 但我相信取消触摸cancelsTouchesInView
只取消一个特定的触摸事件,不转发。
任何其他方式来实现我的要求? 我准备根据你提供的任何提示工作。
编辑:美好的时光
我所谓的subView A实际上是第三方库的View类的一个实例,它需要所有的触摸,我没有任何手势的控制。 我想要左右滑动的不同实现,我想捏,轻拍等工作,就像它正在与这个第三方视图工作。 所以我在A(SubView B)的顶部放置一个视图来左右滑动。 但是现在我想将其他手势事件转发到底层库。
如果我解决你的问题是正确的,你可以添加另一个清晰的视图与矩形,与你A和B视图一样,并实现所有的手势:当你捏手势,控制子视图A时,轻扫和单击双)手势 – 控制子视图B.你可以做不同的方式:通过指针或只是发送recived手势类中的方法,这将控制你的子视图。
例如:
UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)]; [leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)]; leftSwipe.delegate = subViewAcontroller; [clearView addGestureRecognizer:leftSwipe]; [leftSwipe release]; UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)]; [rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)]; rightSwipe.delegate = subViewAcontroller; [clearView addGestureRecognizer:rightSwipe]; [rightSwipe release]; UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)]; pinch.delegate = subViewBcontroller; [clearView addGestureRecognizer:pinch]; [pinch release];
要么:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) { NSLog(@"pinchGesture"); [subViewBcontroller solvePinchGesture: gestureRecognizer]; } //etc return YES; }
夹点手势将永远不会被aView接收,因为您的视图层次结构不正确。
---> A superView | ---> SubView - A | ---> SubView - B (exactly on top of A, completely blocking A).
bView将捕获包括捏手势的所有多触摸,但是bView不会处理捏手势,所以它将它传递给响应者链中的下一响应者,即bView的超视图或bView的视图控制器。 捏事件将永远不会传递给它的同级视图,因为它们并行(没有父子关系或view-viewController关系)。
你可以改变你的视图层次如下:
---> A superView | ---> SubView - A | ---> SubView - B (child view of b, exactly on top of A, completely blocking A) - (void)viewDidLoad { [super viewDidLoad]; aView = [[UIView alloc] initWithFrame:self.view.bounds]; aView.backgroundColor = [UIColor blueColor]; bView = [[UIView alloc] initWithFrame:self.view.bounds]; bView.backgroundColor = [UIColor redColor]; [self.view addSubview:aView]; [aView addSubview:bView]; UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)]; [leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)]; leftSwipe.delegate = self; [bView addGestureRecognizer:leftSwipe]; UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)]; [rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)]; rightSwipe.delegate = self; [bView addGestureRecognizer:rightSwipe]; UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)]; pinch.delegate = self; [aView addGestureRecognizer:pinch]; }
请从下面的链接获取更多信息: https : //developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/EventsiPhoneOS/EventsiPhoneOS.html#//apple_ref/doc/uid/TP40009541-CH2-SW1
– >传递给响应者链的事件的重要注意事项“当系统传递一个触摸事件时,它首先将其发送到一个特定的视图,对于触摸事件,该视图是由hitTest:withEvent返回的视图: “动作事件,远程控制事件,动作消息和编辑菜单消息,视图是第一响应者,如果初始视图不处理事件,则沿着特定的path向上传递响应者链:
- 命中testing视图或第一响应者将事件或消息传递给它的视图控制器(如果有); 如果视图没有视图控制器,它将事件或消息传递给它的超级视图。
- 如果视图或其视图控制器无法处理该事件或消息,则将其传递给视图的超级视图。
- 如果不能处理事件或消息,则层次结构中的每个后续超级视图都遵循前两个步骤中描述的模式。
- 如果视图层次结构中最顶层的视图不处理事件或消息,则将其传递给窗口对象进行处理。
- 如果UIWindow对象不处理事件或消息,则将其传递给单例应用程序对象。
我上面的答案不是唯一的解决scheme,你需要做的是在相同的响应者链中进行滑动和捏手势处理逻辑,所以不处理捏手势事件将传递给正确的响应者。 例如,您可以省略子视图b,并将左右滑动手势添加到aView的超级视图。
我前段时间做了类似的事情。 我想用一个手指和两个或更多的手指做两件不同的事情。 我的解决scheme可能需要一些调整,我不能确保你的代码环境中的一切都会完全相同。 我没有find适当的hitTest文档,为什么它连续多次被调用。 所以我做了一些testing,得出了一个解决scheme,如何分离一个和多个手指的手势,这对我的需求非常好。
我有这个视图层次结构:
---> A superView | ---> ScrollView - A - all touches | ---> ScrollView - B - only two+ finger scroll (exactly on top of A, completely blocking A).
我在superView的hitTest中实现了这个开关:
BOOL endDrag; // indicates scrollviewB did finish BOOL shouldClearHitTest; // bool to help calling the method clearHitTest only once. BOOL multiTouch; // needed for the method clearHitTest to know if a multi-touch is detected or not NSMutableArray *events; // store all events within one eventloop/touch; - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (!endDrag) { if (!shouldClearHitTest) { // as hitTest will be called multible times in one event-loop and i need all events, i will clean the temporaries when everything is done shouldClearHitTest = YES; [[NSRunLoop mainRunLoop] performSelector:@selector(clearHitTest) target:self argument:nil order:1 modes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; } [events addObject:event]; // store the events so i can access them after all hittests for one touch are evaluated if (event.type == UIEventTypeTouches && ([_events count] > 3 || [[event allTouches] count] > 0 || _currentEvent)) { // two or more fingers detected. at least for my view hierarchy multiTouch = YES; return scrollViewB; } }else { endDrag = NO; } return scrollViewA; } - (void)clearHitTest { if (shouldClearHitTest) { shouldClearHitTest = NO; [events removeAllObjects]; if (multiTouch) { // Do some special stuff for multiTouch } multiTouch = NO; } }
我build议你在需要的地方使用下面的代码行可以帮助你。
//--->for bview gesture to detect swipe [pinch requireGestureRecognizerToFail:leftSwipe]; && [pinch requireGestureRecognizerToFail:rightSwipe]; //--->for aview gesture to detect pinch [rightSwipe requireGestureRecognizerToFail:rightSwipe]; || [leftSwipe requireGestureRecognizerToFail:pinch];
如果bView有捏手势。 从bView的捏手势动作,如果称为aView的捏手势动作,然后…
UIPinchGestureRecognizer *pinchA = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinchA:)]; [aView addGestureRecognizer:pinchA]; [pinchA release]; UIPinchGestureRecognizer *pinchB = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinchB:)]; [bView addGestureRecognizer:pinchB]; [pinchB release]; -(void)handlePinchA:(UIGestureRecognizer*)gestureRecognizer { NSLog(@"handlePinch on A"); } -(void)handlePinchB:(UIGestureRecognizer*)gestureRecognizer { NSLog(@"handlePinch on B"); [self handlePinchA:gestureRecognizer]; }
aView是第三方库。 你可以从外面调用handlePinchA方法吗? NSLog的gestureRecognizers打印我action = handlePinchA
NSLog(@"gestureRecognizers %@", [aView gestureRecognizers]);
打印我:
gestureRecognizers ( "<UIPinchGestureRecognizer: 0x8b3e500; state = Possible; view = <UIView 0x8b2f470>; target= <(action=handlePinchA:, target=....
- 用Swift在iOS中发送短信
- UIImageView在设备上启动屏幕上丢失的图像
- iOS中的NSURLConnection和基本HTTP身份validation
- 如何创build应用程序加载器的上传文件?
- NSManagedObjectContext performBlockAndWait:不在后台线程上执行?
- 当iOS应用程序第一次启动时检测?
- 如何从弱财产中清除KVO?
- iOS8:退出应用程序后不久,蓝条“正在使用你的位置”出现
- 命令/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang失败,退出代码1