通过触摸到下面的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或XIBselect您的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 。