标题很难。 主要案例是这样的
UIView *superView = [[UIView alloc] initWithFrame:CGRectMake(0,0,400,400)];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(-200,-200,400,400)];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[subView addGestureRecognizer:tapGesture];
[superView addSubView:subView];
好的,你会发现当点击(0,0,200,200)中的区域时点击手势将生效,如果点击该点(-150,-150),点击手势将不会生效。
我不知道superView外部的点击是否会导致此问题。
任何人都知道如何解决这个问题?
答案 0 :(得分:11)
要允许位于超级视图外部的子视图响应触摸,请覆盖超级视图的hitTest:withEvent:
。
Documentation on Event Delivery
触摸事件。窗口对象使用命中测试和响应者链来查找接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶层视图上调用hitTest:withEvent:此方法通过在视图层次结构中返回YES的每个视图上递归调用pointInside:withEvent:继续执行,继续向下移动层次结构,直到找到触摸发生在其边界内的子视图。该视图成为热门测试视图。
在子类中添加以下方法:
(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
UIView *iSubView;
while ((iSubView = [reverseE nextObject])) {
UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
if(viewWasHit) {
return viewWasHit;
}
}
return [super hitTest:point withEvent:event];
}
注意:由于子视图是从后到前排序的,因此我们希望首先测试最前面的视图。
答案 1 :(得分:2)
我发现这种情况的唯一解决方法是创建一个视图实例,该视图对于作为主视图的触摸是透明的。在这种情况下,内部视图将响应触摸,因为它适合主要的边界。在我通过网络中发现的不同示例制作的课程中,我可以控制“触摸可见性”的级别,如下所示: 完全可见 - 所有触摸最终都在视图中。 只有子视图 - 视图本身不可见,但子视图会触及它们。 完全看不见 - 我认为非常自我解释:)
我没有尝试将它与手势识别器一起使用,但我不认为会有任何问题,因为它与常规触摸完美配合。
代码很简单......
<强> TransparentTouchView.h 强>
#import <UIKit/UIKit.h>
typedef enum{
TransparencyTypeNone = 0, //act like usual uiview
TransparencyTypeContent, //only content get touches
TransparencyTypeFull //fully transparent for touches
}TransparencyType;
@interface TransparentTouchView : UIView {
TransparencyType _transparencyType;
}
@property(nonatomic,assign)TransparencyType transparencyType;
@end
<强> TransparentTouchView.m 强>
#import "TransparentTouchView.h"
@implementation TransparentTouchView
@synthesize
transparencyType = _transparencyType;
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// UIView will be "transparent" for touch events if we return NO
switch (_transparencyType) {
case TransparencyTypeContent:
for(UIView* subview in self.subviews){
CGPoint p = [subview convertPoint:point fromView:self];
if([subview pointInside:p withEvent:event]){
return YES;
}
}
return NO;
break;
case TransparencyTypeFull:
return NO;
default:
break;
}
return YES;
}
@end
我相信你可以满足你的需求。