通过触摸到下面的UIViews
我有一个UIView
与4个button和另一个UIView
在button视图的顶部。 最上面的视图包含一个带有UITapGestureRecognizer
的UIImageView
。
我试图创build的行为是,当用户点击UIImageView
它在屏幕的右下angular变小,animation变大。 当它很大时,我希望底部视图上的button被禁用,当它很小并且在右下angular时,我希望将触摸传递给button,并使其正常工作。 我几乎在那里,但我不能得到的触摸通过button,除非我禁用顶视图的UserInteractions
。
我有这个在我的initWithFrame:
顶视图:
// Add a gesture recognizer to the image view UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageTapped:)]; tapGestureRecognizer.cancelsTouchesInView = NO; [imageView addGestureRecognizer:tapGestureRecognizer]; [tapGestureRecognizer release];
而我这是我的imageTapped:
方法:
- (void) imageTapped:(UITapGestureRecognizer *) gestureRecognizer { // Toggle between expanding and contracting the image if (expanded) { [self contractAnimated:YES]; expanded = NO; gestureRecognizer.cancelsTouchesInView = NO; self.userInteractionEnabled = NO; self.exclusiveTouch = NO; } else { [self expandAnimated:YES]; expanded = YES; gestureRecognizer.cancelsTouchesInView = NO; self.userInteractionEnabled = YES; self.exclusiveTouch = YES; } }
使用上面的代码,当图像很大时,button是不活动的,当我触摸图像时,它缩小,button变成活动的。 但是,小图像没有收到触摸,因此不会扩大。
如果我在这两种情况下设置了self.userInteractionEnabled = YES
,那么图片会在触摸时展开和收缩,但是button永远不会触摸,并且会像禁用一样操作。
触摸时是否有图像展开和收缩,但是下面的button是否只在图像处于收缩状态时才会接触到图像? 我在这里做了些什么愚蠢的事情,想念一些明显的东西?
我疯了试图让这个工作,所以任何帮助将不胜感激,
戴夫
更新:
为了进一步testing,我touchesCancelled:
了touchesBegan:
和touchesCancelled:
方法,并在包含UIImageView的视图上调用它们的超级实现。 通过上面的代码, touchesCancelled:
永远不会被调用,而touchesBegan:
总是被调用。
所以看起来这个视图正在触及,他们只是没有传递到下面的视图。
UPDATE
这是因为响应者链的工作方式? 我的视图层次结构如下所示:
VC - View1 -View2 -imageView1 (has tapGestureRecogniser) -imageView2 -View3 -button1 -button2
我认为操作系统首先做一个hitTest,因为View2在前面所以应该得到所有的触摸,这些都不会传递到View3,除非View2的userInteractions设置为NO,在这种情况下,imageView1也被阻止接收触摸。 这是如何工作的,有没有办法让View2通过View3的触摸?
UIGestureRecognizer是我认为的一个红鲱鱼。 最后解决这个问题我重覆了一下pointInside:withEvent:
我的UIView:
pointInside:withEvent:
方法UIView:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { BOOL pointInside = NO; if (CGRectContainsPoint(imageView.frame, point) || expanded) pointInside = YES; return pointInside; }
这会导致视图捕捉所有触摸如果您触摸imageView或其扩展标志设置。 如果它没有展开,那么只有在imageView上的时候才会捕获触摸。
通过返回NO,顶层VC的视图查询其视图层次结构的其余部分寻找一个命中。
在Storyboard
或XIB
select您的View
…
更经常地使用Storyboard
,对于这样简单的调整来说非常棒!
或者在Swift 3中
view.isUserInteractionEnabled = false
查看UIGestureRecognizerDelegate协议 。 具体来说, gestureRecognizer:shouldReceiveTouch:
你会想让每个UIGestureRecognizer
成为你的UIViewController
一个属性,
// .h @property (nonatomic, strong) UITapGestureRecognizer *lowerTap; // .m @synthesize lowerTap; // When you are adding the gesture recognizer to the image view self.lowerTap = tapGestureRecognizer
确保你让你的UIViewController
成为一个委托,
[self.lowerTap setDelegate: self];
那么,你会有这样的事情,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if (expanded && gestureRecognizer == self.lowerTap) { return NO; } else { return YES; } }
当然,这不是确切的代码。 但是这是你想要遵循的一般模式。
我有另一个解决scheme。 我有两个视图,我们称它们为重叠的CustomSubView
,它们都应该接受触摸。 所以我有一个视图控制器和一个自定义UIView类,让我们调用它在界面生成器中设置的ViewControllerView
,然后我添加了两个视图,应该接受触摸到该视图。
所以我通过覆盖hitTest拦截ViewControllerView
的触摸:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return self; }
然后我在ViewControllerView
覆盖:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; for (UIView *subview in [self.subviews reverseObjectEnumerator]) { if ([subview isKindOfClass:[CustomSubView class]]) { [subview touchesBegan:touches withEvent:event]; } } }
做与touchesEnded
touchesCancelled
完全相同touchesEnded
touchesCancelled
。