手勢和觸控基礎知識
web
觸摸控制 是 iOS 系統交互的核心方式。設計模式
Cocoa Touch 以儘量簡單地方式實現了直接的操控。它會把觸控事件發送給你正在進行交互的視圖。spa
每一次觸控都會轉達不少的信息: 觸控發生的位置,點擊屏幕的次數,觸控發生的時間。.net
iOS 使用 responder chain (響應鏈) 來肯定到底是哪一個對象應該對觸控作出響應。 響應者(responders)是響應 事件(event) 的對象。 這些響應者扮演的角色就比如是一串管理者,對這些 事件(event)進行管理。當用戶觸摸屏幕時,應用會去尋找一個對象來處理這一個觸控事件。 觸摸(touch)被傳遞下去,從一個視圖到另一個視圖,直到一些對象來接管而且對這個 事件(event)作出響應。設計
在大多數狀況下,觸摸(touches)以及其信息 被存儲在 UITouch 對象中,觸摸(touches)被做爲一組一組的形式在 UIEvent 對象中傳遞。每個 UIEvent 對象都表明了一個單一的 觸控事件,包含一次或屢次觸摸。這一點既決定了開發者如何去響應用戶的操做,也決定了用戶怎麼在屏幕上進行操做。code
你的應用經過 視圖 或者 視圖控制器 來接收 觸摸(touches)。實現處理 觸摸(touch)的類須要經過繼承 UIResponder 類來實現。 你將會決定在哪兒處理和響應這些 觸摸(touches)。 那些嘗試不使用 responder 類來實現簡單手勢控制的開發新人會遇到不少麻煩。orm
在視圖上處理 觸摸(touches) 看似違反直覺。你可能想去把界面顯示的方式和它對 touches 作出響應的方式分離開。進一步說,視圖直接響應觸控來實現交互看似違反了 MVC 設計模式,可是這樣作是頗有必要的,並且能夠提升封裝性。對象
touches 是具備生命週期的。任意一個 touch 都會經歷五個階段。blog
UITouchPhaseBegan - 當用戶剛接觸屏幕的時候繼承
UITouchPhaseMoved - 當這個接觸動做在屏幕上移動時
UITouchPhaseStationary - 當一個接觸動做在屏幕上中止住時
UITouchPhaseEnded - 當用戶的手指從屏幕上移開時
UITouchPhaseCancelled - 當 iOS 系統中止跟蹤一個 touch 時。 一般發生在,系統中斷或者是視圖從窗口移除或者是處在非激活狀態(有來電)。
這五個階段用來劃分一個觸控事件發生過程當中的整個流程。
全部 UIResponder 類的子類,包括 UIView 和 UIViewController 都會對 touches 作出響應。每個類都決定了自身是否響應或者是如何去響應。當須要去作出響應時,這些類的實例會對用戶的觸控按照本身的方式進行響應。
預約義的回調方法能處理觸控開始,觸控移動,觸控結束這幾種情形。和 階段(Phase)相對應。方法以下:
touchesBegan: withEvent: - 在觸控剛剛發生的時候被調用
touchesMoved: withEvent: - 在觸控移動的時候被調用
touchesEnded: withEvent: - 在觸控結束的時候被調用
touchesCancelled: withEvent: - 當系統強行中斷觸控事件的時候,該方法會被調用(舉例:你正在刷微博,忽然有人來電,該方法就是在此刻被調用的)
上面的每個方法都屬於 UIResponder 方法,一般在 一個 UIView 或是 UIViewController 的子類中進行實現。 這些方法內部並無實現什麼功能。當你想把觸控動做添加到應用時,就應該重載這些方法,實現本身須要的功能。 注意:在UITouchPhaseStationary 階段,沒有方法會被回調。
經過手勢識別器類,當用戶進行輕擊、縮放、旋轉、橫掃、拖動或是一個長按動做時,咱們能夠觸發回調方法。
幾種常見的手勢 1. Taps - 輕擊,一指或多指 2. Swipes - 橫掃 3. Pinches - 捏縮 4. Rotations - 雙指進行視圖的旋轉 5. Pans - 拖拽進行平移 6. Long presses - 長按
當你在處理直接操縱時,你的設計中心會由 UIViewController 移向 UIView. 更確切的說,應該是移向了 UIResponder。你經過自定義一個從UIResponder類中獲取的方法,來建立一個能夠進行觸控的界面。
方法 1-1 這個例子建立了一個 UIImageView類的子類,名爲 DragView,而且把觸控響應添加到了這個子類中。 因爲它是一個圖片視圖,它可以與用戶進行交互就顯得尤其重要(也就是說, setUserInteractionEnabled 屬性必須被設置爲 YES)。這個屬性會影響這個視圖自己以及它全部的子視圖。代碼以下:
@implementation DragView { CGPoint startLocation; } // 初始化方法 - (id)initWithImage:(UIImage *)image { self = [super initWithImage:image]; if (self) { // 在初始化成功後,讓該 DragView 實例對象具有可交互性 self.userInteractionEnabled = YES; } return self; } // Responder 類中的接口方法 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 計算而且存儲偏移量, 把相應觸控的視圖置頂 startLocation = [[touches anyObject] locationInView:self]; [self.superview bringSubviewToFront:self]; } // Responder 類中的接口方法 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { // 計算偏移量 CGPoint point = [[touches anyObject] locationInView:self]; float dx = point.x - startLocation.x; float dy = point.y - startLocation.y; // 計算視圖新的中心點座標 CGPoint newCenter = CGPointMake(self.center.x + dx, self.center.y + dy); // 肯定視圖新的位置 self.center = newCenter; }
知識預備
AffineTransform 仿射變換 - 能夠經過一系列的原子變換的複合來實現,包括:平移(Translation)、縮放(Scale)、翻轉(Flip)、旋轉(Rotation)和錯切(Shear)(圖像的錯切其實是平面景物在投影平面上的非垂直投影)。
iOS 視圖的 frame 和 bounds 屬性的區別: http://blog.csdn.net/mad1989/article/details/8711697
frame: 該view在父view座標系統中的位置和大小。(參照點是,父親的座標系統) bounds:該view在本地座標系統中的位置和大小。(參照點是,本地座標系統,就至關於ViewB本身的座標系統,以0,0點爲起點) center:該view的中心點在父view座標系統中的位置和大小。(參照點是,父親的座標系統)
-(CGRect)frame{ return CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height); } -(CGRect)bounds{ return CGRectMake(0,0,self.frame.size.width,self.frame.size.height); }
Jan 4, 2015