2011-01-28 145 views
94

我有一個看起來是這樣的視圖層次:手勢識別和按鈕動作

UIView (A) 
UIView > UIImageView 
UIView > UIView (B) 
UIView > UIView (B) > Rounded Rect Button 
UIView > UIView (B) > UIImageView 
UIView > UIView (B) > UILabel 

我已經附加手勢識別(縣)我UIView(B)。我面臨的問題是,我沒有得到UIView(B)內的Rounded Rect按鈕的任何操作。 singleTap手勢識別器捕獲/覆蓋按鈕的Touch Up Inside事件。

我該如何讓它工作?我認爲響應者鏈層次結構將確保按鈕觸摸事件將被優先考慮,並且會被觸發!我錯過了什麼?

下面是一些相關的代碼:

#pragma mark - 
#pragma mark View lifecycle (Gesture recognizer setup) 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // double tap gesture recognizer 
    UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)]; 
    dtapGestureRecognize.delegate = self; 
    dtapGestureRecognize.numberOfTapsRequired = 2; 
    [self.viewB addGestureRecognizer:dtapGestureRecognize]; 

    // single tap gesture recognizer 
    UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)]; 
    tapGestureRecognize.delegate = self; 
    tapGestureRecognize.numberOfTapsRequired = 1; 
    [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize]; 
    [self.viewB addGestureRecognizer:tapGestureRecognize]; 

    // add gesture recodgnizer to the grid view to start the edit mode 
    UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)]; 
    pahGestureRecognizer.delegate = self; 
    pahGestureRecognizer.minimumPressDuration = 0.5; 
    [self.viewB addGestureRecognizer:pahGestureRecognizer]; 

    [dtapGestureRecognize release]; 
    [tapGestureRecognize release]; 
    [pahGestureRecognizer release]; 
} 

#pragma mark - 
#pragma mark Button actions 

- (IBAction)buttonTouchUpInside:(id)sender { 
    NSLog(@"%s, %@", __FUNCTION__, sender); 
} 

#pragma mark - 
#pragma mark Gesture recognizer actions 


- (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { 
    NSLog(@"%s", __FUNCTION__); 
} 

- (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { 
    NSLog(@"%s", __FUNCTION__); 
} 

- (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer { 

    switch (gestureRecognizer.state) { 

     case UIGestureRecognizerStateEnded: { 
      NSLog(@"%s", __FUNCTION__); 

      break; 
     } 
     default: 
      break; 
    } 
} 
+0

最簡單的方法是設置cancelsTouchesInView =假 – 2017-06-02 10:10:12

回答

165

在你要補充一點,將不返回觸摸是否在按鈕的條件了「shouldReceiveTouch」的方法。

這是來自蘋果SimpleGestureRecognizers的例子。

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

    // Disallow recognition of tap gestures in the segmented control. 
    if ((touch.view == yourButton)) {//change it to your condition 
     return NO; 
    } 
    return YES; 
} 

希望這將有助於

編輯

正如丹尼爾指出您必須遵守UIGestureRecognizerDelegate爲它工作。

SHANI

+1

啊!是的,我忘了這個-gestureRecognizer:shouldReceiveTouch:方法。感謝您指點我正確的方向。雖然這解決了我的問題,但我仍然不知道爲什麼響應者層次結構在這種情況下不起作用。它可能應該,但它不是由蘋果公司處理。 – Mustafa 2011-01-28 07:29:25

+2

UIGestureRecognizer行爲被清楚地描述爲與「普通」響應者鏈分開。 這是由Apple設計決定的。 – 2011-02-17 12:48:15

48

我也有同樣的問題,那我就用

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

    if ([touch.view isKindOfClass:[UIButton class]]) {  //change it to your condition 
     return NO; 
    } 
    return YES; 
} 

它現在完美的工作.........

18

一般來說,我們使用下面的委託方法,以避免各種UIControls的觸摸:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 
    if (([touch.view isKindOfClass:[UIControl class]])) { 
     return NO; 
    } 
    return YES; 
} 

注意:不要做這種檢查(C heck the recognitionizer.view類類型)gestureRecognizerShouldBegin,它不會工作。

4

最好的解決辦法是在我的腦海使用下面的代碼片段:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 
    CGPoint touchLocation = [touch locationInView:self.view]; 
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation); 
} 
6

這裏是一個斯威夫特版本:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { 
    if (touch.view!.isKindOfClass(UIButton)) { 
     return false 
    } 
    return true 
} 

不要忘記:

  1. 讓你類符合UIGestureRecognizerDelegate
  2. 使您的tapper對象de legate to self(例如:tapper.delegate = self
6

這是斯威夫特3。0版本:

extension UIViewController: UIGestureRecognizerDelegate { 

public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { 
    if touch.view is UIButton { 
     return false 
    } 
    return true 
} 

不要忘記:

Make your tapper object delegate to self (e.g: tapper.delegate = self)