在下面传递对 UIView 的触摸

我有一个 UIView与4个按钮上,另一个 UIView上的按钮视图。最上面的视图包含一个 UIImageView,上面有一个 UITapGestureRecognizer

我试图创建的行为是,当用户点击 UIImageView时,它在屏幕右下角的小和动画变大之间切换。当它是大的时候,我希望底部视图上的按钮被禁用,当它是小的时候,在右下角,我希望触摸被传递到按钮,并为他们正常工作。我几乎在那里,但我不能得到的触摸通过的按钮,除非我禁用的 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;
}
}

使用上面的代码,当图像很大时,按钮是不活动的,当我触摸图像时,它会收缩,按钮变成活动的。然而,小图像不接受触摸,因此不会扩大。

如果我在这两种情况下设置 self.userInteractionEnabled = YES,然后图像扩展和收缩时,触摸,但按钮从来没有接收触摸和行动,好像禁用。

是否有办法使图像在触摸时扩展和收缩,但是下面的按钮只有在图像处于收缩状态时才能接收触摸?我是不是做了什么蠢事,漏掉了什么显而易见的东西?

我为了让这东西起作用都快疯了这样我才会感激你的帮助,

戴夫

更新:

为了进一步测试,我覆盖了 touchesBegan:touchesCancelled:方法,并在包含 UIImageView 的视图上调用了它们的超级实现。对于上面的代码,从不调用 touchesCancelled:,而总是调用 touchesBegan:

因此,看起来视图正在接触,它们只是没有传递给下面的视图。

更新

这是因为响应链的工作方式吗? 我的视图层次结构如下:

VC - View1
-View2
-imageView1 (has tapGestureRecogniser)
-imageView2
-View3
-button1
-button2

我认为操作系统首先做了一个点击测试,因为 View2在前面,所以应该得到所有的触摸,除非用户交互被设置为 NO,否则这些不会传递给 View3,在这种情况下 imageView1也被阻止接收触摸。这就是它的工作原理吗? 有没有办法让 View2通过它对 View3的接触?

75826 次浏览

看看 委托协议特别是 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;
}
}

当然,这不是精确的代码,但是这是您希望遵循的一般模式。

我认为 UIGestureIdentiizer 是一个转移注意力的东西。最后,为了解决这个问题,我重写了 UIView:pointInside:withEvent:方法

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
BOOL pointInside = NO;


if (CGRectContainsPoint(imageView.frame, point) || expanded) pointInside = YES;


return pointInside;
}

这导致视图陷入所有触摸,如果您触摸的 ImageView 或如果其扩展标志设置。如果它没有展开,那么只有陷阱的触摸,如果他们是在 image 视图。

通过返回 NO,顶级 VC 的 View 查询其他视图层次结构,寻找命中。

Storyboard或者 XIB中选择你的 View,然后..。


enter image description here


或者斯威夫特

view.isUserInteractionEnabled = false

我有另一个办法。我有两个视图,让我们称他们为 CustomSubView,这是重叠的,他们都应该接受触摸。所以我有一个视图控制器和一个自定义的 UIView 类,让我们把它称为我在 Interface Builder 中设置的 ViewControllerView,然后我添加了两个视图,这两个视图应该接收该视图的触摸。

所以我在 ViewControllerView中改写了 hit Test:

- (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];
}
}
}

touchesMoved touchesEndedtouchesCancelled做完全相同的操作。

@ 神奇子弹戴夫的解决方案,但在斯威夫特

Swift 3

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
var pointInside = false
if commentTextField.frame.contains(point) {
pointInside = true
} else {
commentTextField.resignFirstResponder()
}
return pointInside
}

我在我的 CameraOverlayView for ImagePickerViewController.cameraOverlay 中使用它,让用户在拍摄新照片时能够进行评论