2013-04-11 113 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