ios 通过触摸传递到下面的 UIViews
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9026097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing through touches to UIViews underneath
提问by Magic Bullet Dave
I have a UIView
with 4 buttons on it and another UIView
on top of the buttons view. The top most view contains a UIImageView
with a UITapGestureRecognizer
on it.
我有一个UIView
带有 4 个按钮的按钮,另一个UIView
位于按钮视图的顶部。最上面的视图包含UIImageView
带有 的UITapGestureRecognizer
。
The behavtheitroad I am trying to create is that when the user taps the UIImageView
it toggles between being small in the bottom right hand corner of the screen and animating to become larger. When it is large I want the buttons on the bottom view to be disabled and when it is small and in the bottom right hand corner I want the touches to be passed through to the buttons and for them to work as normal. I am almost there but I cannot get the touches to pass through to the buttons unless I disable the UserInteractions
of the top view.
我试图创建的行为是,当用户点击UIImageView
它时,它会在屏幕右下角的小屏幕和动画变大之间切换。当它很大时,我希望底部视图上的按钮被禁用,当它很小并且在右下角时,我希望将触摸传递到按钮并让它们正常工作。我快到了,但除非禁用UserInteractions
顶视图的,否则我无法触摸到按钮。
I have this in my initWithFrame:
of the top view:
我在我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];
and I this is my imageTapped:
method:
我这是我的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;
}
}
With the above code, when the image is large the buttons are inactive, when I touch the image it shrinks and the buttons become active. However, the small image doesn't receive the touches and therefore wont expand.
使用上面的代码,当图像很大时按钮处于非活动状态,当我触摸图像时它会缩小并且按钮变为活动状态。但是,小图像不会受到触摸,因此不会扩展。
If I set self.userInteractionEnabled = YES
in both cases, then the image expands and contracts when touched but the buttons never receive touches and act as though disabled.
如果我self.userInteractionEnabled = YES
在这两种情况下都设置,那么图像在触摸时会扩展和收缩,但按钮永远不会收到触摸并表现为好像被禁用。
Is there away to get the image to expand and contract when touched but for the buttons underneath to only receive touches if the image is in its contracted state? Am I doing something stupid here and missing something obvious?
有没有办法让图像在触摸时扩展和收缩,但如果图像处于收缩状态,下面的按钮只能接收触摸?我在这里做了一些愚蠢的事情而错过了一些明显的事情吗?
I am going absolutely mad trying to get this to work so any help would be appreciated,
我要让这个工作变得非常疯狂,所以任何帮助将不胜感激,
Dave
戴夫
UPDATE:
更新:
For further testing I overrode the touchesBegan:
and touchesCancelled:
methods and called their super implementations on my view containing the UIImageView. With the code above, the touchesCancelled:
is never called and the touchesBegan:
is always called.
为了进一步测试,我覆盖了touchesBegan:
和touchesCancelled:
方法,并在包含 UIImageView 的视图上调用了它们的超级实现。使用上面的代码,touchesCancelled:
永远不会调用 ,而touchesBegan:
始终调用 。
So it would appear that the view is getting the touches, they are just not passed to the view underneath.
所以看起来视图正在得到触摸,它们只是没有传递到下面的视图。
UPDATE
更新
Is this because of the way the responder chain works? My view hierarchy looks like this:
这是因为响应者链的工作方式吗?我的视图层次结构如下所示:
VC - View1
-View2
-imageView1 (has tapGestureRecogniser)
-imageView2
-View3
-button1
-button2
I think the OS first does a hitTest as says View2 is in front so should get all the touches and these are never passed on to View3 unless userInteractions is set to NO for View2, in which case the imageView1 is also prevented from receiving touches. Is this how it works and is there a way for View2 to pass through it's touches to View3?
我认为操作系统首先执行 hitTest,因为 View2 位于前面,因此应该获取所有触摸,并且这些触摸永远不会传递给 View3,除非 userInteractions 为 View2 设置为 NO,在这种情况下,imageView1 也无法接收触摸。这是它的工作方式吗?有没有办法让 View2 通过它的触摸传递到 View3?
回答by Magic Bullet Dave
The UIGestureRecognizer is a red herring I think. In the end to solve this I overrode the pointInside:withEvent:
method of my UIView:
UIGestureRecognizer 是我认为的红鲱鱼。最后为了解决这个问题,我覆盖了我的pointInside:withEvent:
方法UIView:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
BOOL pointInside = NO;
if (CGRectContainsPoint(imageView.frame, point) || expanded) pointInside = YES;
return pointInside;
}
This causes the view to trap all touches if you touch either the imageView or if its expanded flag is set. If it is not expanded then only trap the touches if they are on the imageView.
如果您触摸 imageView 或设置了其扩展标志,这会导致视图捕获所有触摸。如果未展开,则仅捕获在 imageView 上的触摸。
By returning NO, the top level VC's View queries the rest of its view hierarchy looking for a hit.
通过返回 NO,顶级 VC 的 View 查询其视图层次结构的其余部分以寻找命中。
回答by Michael
Select your View
in Storyboard
or XIB
and...
选择您的View
inStoryboard
或XIB
and...
Or in Swift
或者在斯威夫特
view.isUserInteractionEnabled = false
回答by john
Look into the UIGestureRecognizerDelegate Protocol. Specifically, gestureRecognizer:shouldReceiveTouch:
查看UIGestureRecognizerDelegate 协议。具体来说,gestureRecognizer:shouldReceiveTouch:
You'll want to make each UIGestureRecognizer
a property of your UIViewController
,
你会想让每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
Make sure you make your UIViewController
a delegate,
确保你成为你UIViewController
的代表,
[self.lowerTap setDelegate: self];
Then, you'd have something like this,
那么,你会有这样的事情,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (expanded && gestureRecognizer == self.lowerTap) {
return NO;
}
else {
return YES;
}
}
Of course, this isn't exact code. But this is the general pattern you'd want to follow.
当然,这不是确切的代码。但这是您想要遵循的一般模式。
回答by Nico S.
I have a another solution. I have two views, let's call them CustomSubView
that were overlapping and they should both receive the touches. So I have a view controller and a custom UIView class, lets call it ViewControllerView
that I set in interface builder, then I added the two views that should receive the touches to that view.
我有另一个解决方案。我有两个视图,让我们称它们CustomSubView
为重叠的,它们都应该接收触摸。所以我有一个视图控制器和一个自定义 UIView 类,让ViewControllerView
我在界面构建器中设置它,然后我添加了两个应该接收该视图的触摸的视图。
So I intercepted the touches in ViewControllerView
by overwriting hitTest:
所以我ViewControllerView
通过覆盖hitTest来拦截触摸:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
return self;
}
Then I overwrote in ViewControllerView
:
然后我改写了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];
}
}
}
Do the exact same with touchesMoved
touchesEnded
and touchesCancelled
.
与touchesMoved
touchesEnded
和完全相同touchesCancelled
。
回答by imike
@Magic Bullet Dave's solution but in Swift
@Magic Bullet Dave 的解决方案,但在 Swift 中
Swift 3
斯威夫特 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
}
I use it in my CameraOverlayView for ImagePickerViewController.cameraOverlay to give user ability to comment while taking new photo
我在我的 CameraOverlayView 中为 ImagePickerViewController.cameraOverlay 使用它,让用户能够在拍摄新照片时发表评论