0

我試圖創建一個UIPinchGestureRecognizer,如果用戶捏出(移動手指分開)失敗。我知道有一種非常簡單的方法可以通過在操作方法中採用識別器的比例來實現這一點,並且如果它大於1,則設置一個標記並忽略所有未來呼叫。但是,這對我不起作用,我有其他手勢識別器需要此捏夾識別器失敗,所以我需要它在用戶捏住錯誤方向時正常失敗。UIPinchGestureRecognizer僅適用於捏出

我試圖繼承UIPinchGestureRecognizer:

@implementation BHDetailPinchGestureRecogniser { 
    CGFloat initialDistance; 
} 

#pragma mark - Object Lifecycle Methods 

- (id)initWithTarget:(id)target action:(SEL)action { 
    self = [super initWithTarget:target action:action]; 
    if (self) { 
     initialDistance = NSNotFound; 
    } 
    return self; 
} 

#pragma mark - UIGestureRecogniser Methods 

- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)recogniser { 
    if ([recogniser isKindOfClass:[UIPinchGestureRecognizer class]]) { 
     return [self.delegate gestureRecognizerShouldBegin:self]; 
    } else return false; 
} 

- (void)reset { 
    [super reset]; 
    initialDistance = NSNotFound; 
} 

#pragma mark - Touch Handling Methods 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (touches.count >= 2) { 
     if (self.state == UIGestureRecognizerStatePossible) { 
      // Keep hold of the distance between the touches 
      NSArray *bothTouches = [touches allObjects]; 
      CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view]; 
      CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view]; 
      initialDistance = [self distanceBetweenPoint:location1 andPoint:location2]; 
     } 
    } else { 
     // Fail if there is only one touch 
     self.state = UIGestureRecognizerStateFailed; 
    } 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"Moved. (tc, %lu) (state, %i) (id, %f)", (unsigned long)touches.count, self.state, initialDistance); 
    if (touches.count >= 2) { 
     if (self.state == UIGestureRecognizerStatePossible) { 
      if (initialDistance != NSNotFound) { 
       // Get the new distance and see if is is larger or smaller than the original 
       NSArray *bothTouches = [touches allObjects]; 
       CGPoint location1 = [(UITouch *)bothTouches[0] locationInView:self.view]; 
       CGPoint location2 = [(UITouch *)bothTouches[1] locationInView:self.view]; 
       NSLog(@"Checking distance between points."); 
       if ([self distanceBetweenPoint:location1 andPoint:location2] < initialDistance - 3.f) { 
        NSLog(@"Began"); 
        self.state = UIGestureRecognizerStateBegan; 
       } else if ([self distanceBetweenPoint:location1 andPoint:location2] > initialDistance) { 
        NSLog(@"Failed"); 
        self.state = UIGestureRecognizerStateFailed; 
       } 
      } 
     } else { 
      self.state = UIGestureRecognizerStateChanged; 
     } 
    } 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (self.state == UIGestureRecognizerStatePossible) self.state = UIGestureRecognizerStateFailed; 
    else [super touchesEnded:touches withEvent:event]; 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { 
    self.state = UIGestureRecognizerStateCancelled; 
} 

#pragma mark - Helper Methods 

- (CGFloat)distanceBetweenPoint:(CGPoint)point1 andPoint:(CGPoint)point2 { 
    return sqrtf(powf(point1.x - point2.x, 2) + powf(point1.y - point2.y, 2)); 
} 

@end 

我已經意識到,它不是那麼簡單,它需要處理多點觸摸,有時只會接觸移動有一個觸摸,因此將需要保持保持觸動,一觸即可結束,另一個開始,這仍然要成爲捏的一部分。看起來好像我放鬆了夾點識別器的功能構建,當我想要做的就是如果用戶捏在錯誤的方向上使它失敗。

有沒有一種更簡單的方法來實現這種行爲,而不必完全重寫UIPinchGestureRecognizer?可能值得一提的是,我無法控制我想失敗的其他識別器(它們深入到PSPDFViewController(第三方庫)的碗中)。

回答

2

如何使用手勢識別器的delegate提供幫助?

設置一個委託具有以下實現的gestureRecognizerShouldBegin

func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { 
    if let pinch = gestureRecognizer as? UIPinchGestureRecognizer { 
     return pinch.scale < 1 
    } 
    return true 
} 
+0

我給它一個去!我曾經想過,在這個委託方法被調用的時候,比例尺會是1,或者是一些未定義的值...只需一秒... – 2014-11-06 14:21:26

+0

雖然這不會「失敗」,但不會「失敗」 '開始'一個。您可能可以添加代碼以使其失敗。 – 2014-11-06 14:22:54

+0

這完美的作品!非常感謝!這種簡單而優雅的解決方案。看起來我不需要它失敗,我只是需要它不承認。 – 2014-11-06 14:24:15