同级子视图在iPhone中不接收触摸
我有一个视图(同级子视图在iPhone中不接收触摸,iphone,ios,uiview,touchesbegan,uiresponder,Iphone,Ios,Uiview,Touchesbegan,Uiresponder,我有一个视图(parent),其中有两个子视图,一个在顶部(topChild),另一个在底部(bottomChild) 如果我只点击屏幕上的topChild和parent接收触摸事件 我应该更改什么来将触摸事件传播到bottomChild 守则: - (void)viewDidLoad { [super viewDidLoad]; MYView* parent = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
parent
),其中有两个子视图,一个在顶部(topChild
),另一个在底部(bottomChild
)
如果我只点击屏幕上的topChild
和parent
接收触摸事件
我应该更改什么来将触摸事件传播到bottomChild
守则:
- (void)viewDidLoad
{
[super viewDidLoad];
MYView* parent = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
parent.tag = 3;
parent.backgroundColor = [UIColor redColor];
MYView* bottomChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 90, 90)];
bottomChild.tag = 2;
bottomChild.backgroundColor = [UIColor blueColor];
[parent addSubview:bottomChild];
MYView* topChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];
topChild.tag = 1;
topChild.backgroundColor = [UIColor greenColor];
[parent addSubview:topChild];
[self.view addSubview:parent];
}
其中MYView
是UIView
的一个子类,它只记录touchsbegind
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"%d", self.tag);
[super touchesBegan:touches withEvent:event];
}
结果是:
触摸绿色区域会生成以下日志:
TouchTest[25062:f803] 1
TouchTest[25062:f803] 3
我的第一个想法是让parent
将所有touchesomething
调用传播给它的孩子,但是(A)我怀疑可能有一个更简单的解决方案,(B)我不知道是哪个孩子将事件发送给了家长,向同一视图发送两次touchesomething
消息可能会引起恶作剧
问了这个问题后,我发现这建议覆盖
hitTest
,以更改接收触摸的视图。我将尝试这种方法,并在有效的情况下更新问题。这是一个有趣的问题,最好通过重新思考事物的结构来解决。但要使其按照您建议的方式工作,您需要在当前俯视图中捕捉触摸事件,将其传递给父视图,然后通过父视图的所有子视图向下传播。要实现这一点,您需要使用触摸开始:
(或用于拦截触摸的任何其他方法)在所有视图中不执行任何操作,仅在父视图调用的方法中执行操作
这实际上是另一种说法,表示不处理视图中的接触,捕捉它们,但通知父视图,然后根据需要调用子视图方法以产生所需的效果
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Do nothing, parent view calls my parentNotifiedTouchesBegan method
[self.superview touchesBegan:touches withEvent:event];
}
- (void) parentNotifiedTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Act on the touch here just as my sibling views are doing
}
注:我在该代码中将super
更改为self.superview
。根据您正在做的事情,您可能想调用super
的方法,也可能不想调用,调用的位置可能在parentNotifiedTouchesBegan
中
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"%d", self.tag);
[super touchesBegan:touches withEvent:event];
}
当然,您可以知道哪个子视图发送了事件,只需使用自定义方法通知superview,而不是调用它的
touchsbegind:
。使用self
参数。如果您不需要对孩子进行触摸,则设置
bottomChild.userInteractionEnabled = NO;
topChild.userInteractionEnabled = NO;
谢谢你,亚当!此解决方案是否与手势识别器兼容?乍一看,如果我走这条路,我将不得不重新安装车轮。我非常想重新构造东西,但我不知道我的情况如何。topChild具有透明度,topChild和bottomChild都可以“移动”(因此topChild不能是bottomChild的子视图),并且都需要响应触摸。这应该是可能的,您只需将回调接收到的GestureRecognitor对象传递给父对象,而不是简单的触摸。至少在我手边的项目中,这对UIPinchGestureRecognizer是有效的。现在我想你根本不需要在子视图中捕捉事件,事实上你可以禁用交互,这样基础视图就可以获取所有信息。无需执行通知步骤。只需让基本视图捕获并解释所有内容,并使视图发挥作用。您应该能够通过比较点(((CGPoint)convertPoint:(CGPoint)point to view:(UIView*)视图)和子视图的帧(CGRectContainsPoint)来隔离应该获取事件的视图。这就是我现在尝试的!也就是说,我觉得很奇怪,这必须“手动”完成。我想这是一个相当普遍的问题。