2013-04-11 71 views
3

我的界面有时在其外围有按钮。没有按钮的区域接受手势。某些按钮失败hitTest

GestureRecognizers添加到容器视图中的viewDidLoad中。这里的tapGR是如何设置的:

UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playerReceived_Tap:)]; 
[tapGR setDelegate:self]; 
[self.view addGestureRecognizer:tapGR]; 

为了防止手势识别器截获按钮水龙头,我实现shouldReceiveTouch返回YES只有在视图触摸不是按钮:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gr 
    shouldReceiveTouch:(UITouch *)touch { 

    // Get the topmost view that contains the point where the gesture started. 
    // (Buttons are topmost, so if they were touched, they will be returned as viewTouched.) 
    CGPoint pointPressed = [touch locationInView:self.view]; 
    UIView *viewTouched = [self.view hitTest:pointPressed withEvent:nil]; 

    // If that topmost view is a button, the GR should not take this touch. 
    if ([viewTouched isKindOfClass:[UIButton class]]) 
     return NO; 

    return YES; 

} 

这在大多数情况下都能正常工作,但有几个按钮没有响应。当点击这些按钮时,hitTest返回容器视图,而不是按钮,因此shouldReceiveTouch返回YES并且gestureRecognizer指示事件。

要调试,我跑了一些测试...

下面的测试证实,该按钮是容器视图的子子视图,它被启用,并且这两个按钮,分别子视图userInteractionEnabled:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gr 
    shouldReceiveTouch:(UITouch *)touch { 

// Test that hierarchy is as expected: containerView > vTop_land > btnSkipFwd_land. 
for (UIView *subview in self.view.subviews) { 
    if ([subview isEqual:self.playComposer.vTop_land]) 
     printf("\nViewTopLand is a subview."); // this prints 
} 
for (UIView *subview in self.playComposer.vTop_land.subviews) { 
    if ([subview isEqual:self.playComposer.btnSkipFwd_land]) 
     printf("\nBtnSkipFwd is a subview."); // this prints 
} 

// Test that problem button is enabled. 
printf(“\nbtnSkipFwd enabled? %d", self.playComposer.btnSkipFwd_land.enabled); // prints 1 

// Test that all views in hierarchy are interaction-enabled. 
printf("\nvTopLand interactionenabled? %d", self.playComposer.vTop_land.userInteractionEnabled); // prints 1 
printf(“\nbtnSkipFwd interactionenabled? %d", self.playComposer.btnSkipFwd_land.userInteractionEnabled); // prints 1 

// etc 

} 

以下测试确认按下的点实际上在按钮的框架内。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gr 
    shouldReceiveTouch:(UITouch *)touch { 

CGPoint pointPressed = [touch locationInView:self.view]; 
CGRect rectSkpFwd = self.playComposer.btnSkipFwd_land.frame; 

// Get the pointPressed relative to the button's frame. 
CGPoint pointRelSkpFwd = CGPointMake(pointPressed.x - rectSkpFwd.origin.x, pointPressed.y - rectSkpFwd.origin.y); 
printf("\nIs relative point inside skipfwd? %d.", [self.playComposer.btnSkipFwd_land pointInside:pointRelSkpFwd withEvent:nil]); // prints 1 

// etc 

} 

那么为什么hitTest返回容器视图而不是这个按钮?

解决方案:我没有测试的一件事是中间视图vTop_land被正确构筑。它看起来不错,因为它有一个延伸到屏幕的图像 - 超过了它的框架边界(我不知道这是可能的)。该框架设置为纵向宽度,而不是横向宽度,因此最右侧的按钮不在区域内。

回答

2

命中测试在大多数情况下不可靠,通常不建议将它与gestureRecognizers一起使用。

为什么不是你setExclusiveTouch:YES为每个按钮,这应该确保按钮总是选择。

+0

我喜欢这个想法。这听起来比我正在做的更有效率。目前该按钮仍然没有回应,由于其他一些问题,虽然... – Wienke

+0

我已经标记为接受的答案,因为这个建议是如此的好。我在问题的底部添加了实际的解决方案。 – Wienke