2014年2月21日 星期五

偵測多指 Swipe

之前實作過的程式,都是使用單指滑動,我們只是從 touches 集合中抓出任一個物件來計算滑動期間 user 的手指位置。
但如果我們想偵測 2 指或 3 指的滑動呢?

UISwipeGestureRecognizer 可以設定任何數目的同時觸碰。

根據預設,每個實體都是預期一個手指,但我們可以設定它去找尋一次按在螢幕上的任何手指數目。

在實作三指滑動時,記得將 設定 -> 一般 -> 輔助使用 -> 縮放 給關閉,因為縮放預設是使用三指手勢去操控,且於系統裡有較高的優先順序。

程式碼:
#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    for (NSUInteger touchCount = 1; touchCount <= 5; touchCount++) {
        
        UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self 
                                                                                       action:@selector(reportVerticalSwipe:)];
        vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
        vertical.numberOfTouchesRequired = touchCount;
        [self.view addGestureRecognizer:vertical];
        
        UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self 
                                                                                         action:@selector(reportHorizontalSwipe:)];
        horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
        horizontal.numberOfTouchesRequired = touchCount;
        [self.view addGestureRecognizer:horizontal];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    _label = nil;
}

#pragma mark - Added methods

- (void)eraseText {
    _label.text = @"";
}

- (NSString *)descriptionForTouchCount:(NSUInteger)touchCount {
    
    switch (touchCount) {
        case 2:
            return @"Double";
        case 3:
            return @"Triple";
        case 4:
            return @"Quadruple";
        case 5:
            return @"Quintuple";
            
        default:
            return @"";
    }
}

- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer {

    _label.text = [NSString stringWithFormat:@"%@ Horizontal swipe detected”, [self descriptionForTouchCount:[recognizer numberOfTouches]]];
    [self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}

- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer {
    
    _label.text = [NSString stringWithFormat:@"%@ Vertical swipe detected”, [self descriptionForTouchCount:[recognizer numberOfTouches]]];
    [self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}

@end
解釋:
首先,我們以 for 迴圈去指定 vertical、horizontal 實體會回應的切確數目。
ex.
     UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self 
                                                                               action:@selector(reportVerticalSwipe:)];
     vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
     vertical.numberOfTouchesRequired = 3;   <—— 注意這
     [self.view addGestureRecognizer:vertical];
其中 [recognizer numberOfTouches] 因為 user 使用 3 指做觸碰,所以其值為 3。
接著它會呼叫 descriptionForTouchCount: 方法,並將 3 傳入。
- (NSString *)descriptionForTouchCount:(NSUInteger)touchCount {
    switch (touchCount) {
        case 2:
            return @"Double";
        case 3:
            return @"Triple";
        case 4:
            return @"Quadruple";
        case 5:
            return @"Quintuple";
        
        default:
            return @"";
    }
}
descriptionForTouchCount: 因為接收到 3 這個 touchCount 參數,
所以會回傳 @“Triple” 字串,再回到 reportVerticalSwipe: 裡...

_label.text = [NSString stringWithFormat:@"%@ Vertical swipe detected”, 
                                        [self descriptionForTouchCount:[recognizer numberOfTouches]]];

此時 _label.text 所接受到的字串值為 Triple Vertical swipe detected,並將其顯示在螢幕上。