一、基本概念與了解:
Cocoa Touch将觸摸事件發送到正在處理的視圖。觸摸傳達的資訊包括:
- 觸摸發生的位置 (目前位置、最近的曆史位置)
- 觸摸的階段 (按下、移動、彈起)
- 輕擊數量 (tapCount 單擊/輕按兩下)
- 觸摸發生時間 (時間戳)
每個UITouch對象都代表一個觸摸事件。在iPhone中,觸摸互動遵循一種原始的設計模式,即在UIView類中而非UIViewController類中程式設計實作。就是說觸摸互動采用視圖級程式設計方式。
如何觸摸的,即所謂的基本手勢,包括:
- Swipe:滑過,快速移動
- Pinch Open:二指往外撥動
- Pinch Close:二指往内撥動
- Tap:輕擊
- Touch and hold:長按
這些手勢的具體實作最原始的(相對最新的iOS版本)就是通過4個視圖方法自定義程式設計來實作。
二、 觸摸和視圖方法——自定義手勢程式設計
預定義的4個回調方法就是處理螢幕上觸摸的開始、移動和結束。
當使用者開始觸摸螢幕時,在事件的開始階段被調用——touchesBegan: withEvent:
處理手指的移動——touchesMoved: withEvent:
當手指離開螢幕時,結束觸摸過程——touchesEnded: withEvent:
必須響應持續觸摸事件的系統中斷時調用——touchesCancelled: withEvent:
這4個方法都是一種UIResponder方法,通常在UIView子類中實作。所有視圖繼承了這些方法的基本版本。示例:自定義一個Tickle(類似劃卡)手勢。
// TickleGestureRecognizer.h
//
#import <UIKit/UIKit.h>
typedef enum {
DirectionUnknown = 0,
DirectionLeft,
DirectionRight
} Direction;
@interface TickleGestureRecognizer : UIGestureRecognizer
@property (assign) int tickleCount;
@property (assign) CGPoint curTickleStart;
@property (assign) Direction lastDirection;
@end
//
// TickleGestureRecognizer.m
//
#import "TickleGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>
#define REQUIRED_TICKLES 2
#define MOVE_AMT_PER_TICKLE 25
@implementation TickleGestureRecognizer
@synthesize tickleCount;
@synthesize curTickleStart;
@synthesize lastDirection;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
self.curTickleStart = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint ticklePoint = [touch locationInView:self.view];
CGFloat moveAmt = ticklePoint.x - curTickleStart.x;
Direction curDirection;
if (moveAmt < 0) {
curDirection = DirectionLeft;
}else{
curDirection = DirectionRight;
}
if (ABS(moveAmt) < MOVE_AMT_PER_TICKLE) return;
// Make sure we've switched directions
if (self.lastDirection == DirectionUnknown || (self.lastDirection == DirectionLeft && curDirection == DirectionRight) || (self.lastDirection == DirectionRight && curDirection == DirectionRight)) {
self.tickleCount++;
self.curTickleStart = ticklePoint;
self.lastDirection = curDirection;
if (self.state == UIGestureRecognizerStatePossible && self.tickleCount > REQUIRED_TICKLES) {
[self setState:UIGestureRecognizerStateEnded];
}
}
}
- (void)reset {
self.tickleCount = 0;
self.curTickleStart = CGPointZero;
self.lastDirection = DirectionUnknown;
if (self.state == UIGestureRecognizerStatePossible) {
[self setState:UIGestureRecognizerStateFailed];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self reset];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self reset];
}
@end
其中方法locationInView:即擷取目前Touch點位置。若是擷取觸摸動作之前的位置則用previousLocationInView:方法。以上定義了一個TickleGestureRecognizer新類實作了Tickle手勢。具體使用則是:
// 要用手勢的UIView的控制器頭檔案中添加
- (void)handleTickle:(TickleGestureRecognizer *)recognizer;
// 要用手勢的UIView的控制器實作檔案
// viewDidLoad添加
TickleGestureRecognizer *recognizer = [[TickleGestureRecognizer alloc] initWithTarget:self action:@selector(handleTickle:)];
recognizer.delegate = self; // 又見強大的委托
[view addGestureRecognizer:recognizer]; // 用addGestureRecognizer方法将手勢添加到視圖上
// 委托的回調方法
- (void)handleTickle:(TickleGestureRecognizer *)recognizer {
// Code.....
}
三、利用UIGestureRecognizer類給視圖添加手勢
iOS3.0後引入了UIGestueRecognizer類幫助我們處理觸摸動作下各種手勢的添加實作。要點就是在要添加手勢的視圖的控制器類必須實作UIGestureRecognizerDelegate委托協定。其實從編碼角度看,就是蘋果公司将所有的基本手勢由UIGestureRecognizer類來定義實作了(與自定義程式設計中的TickleGestureRecognizer異曲同工)并引入的委托機制。
四、iOS5.0中可以在StoryBoard Editor中可視化添加手勢