知識預備web
什麼是仿射變換?spa
從視覺效果上來理解,仿射變換是經過一系列原子變換複合而來的變換。包括:平移(Translation)、縮放(Scale)、翻轉(Flip)、旋轉(Rotation)和錯切(Shear)(圖像的錯切其實是平面景物在投影平面上的非垂直投影)。.net
iOS 視圖的 frame 和 bounds 屬性的區別code
frame 描述了該視圖在父視圖座標系統中的位置和大小,其參照點是父視圖的座標系統。 bounds 描述了該視圖在本地座標系統中的位置和大小,其參照點是該視圖本身的座標系統。 若是還有疑惑,能夠點擊下方連接,這篇博文確切地解釋了區別所在。 iOS 視圖的 frame 和 bounds 屬性的區別orm
3.UIGestureRecognizerState 的參數值(狀態)對象
UIGestureRecognizerStatePossible : 手勢識別器尚未識別出手勢,可是可能正在估算觸摸事件(touches event),還處在判斷階段。這個狀態是手勢識別器的默認狀態。blog
UIGestureRecognizerStateBegan : 手勢識別器已經接收到了一系列觸摸而且識別出了它屬於哪一個手勢。響應方法在下一個運行週期被調用。繼承
UIGestureRecognizerStateChanged : 手勢識別器已經接收到了一系列觸摸而且識別出手勢發生了改變。響應方法在下一個運行週期被調用。事件
UIGestureRecognizerStateEnded : 手勢識別器已經接收到了一系列觸摸而且識別出手勢剛剛結束。響應方法在下一個運行週期被調用,而且把手勢狀態的值從新置爲 UIGestureRecognizerStatePossible。圖片
UIGestureRecognizerStateCancelled : 手勢識別器已經接收到了一系列觸摸而且識別出手勢忽然中斷。響應方法在下一個運行週期被調用,而且把手勢狀態的值從新置爲 UIGestureRecognizerStatePossible。
UIGestureRecognizerStateFailed : 手勢識別器已經接收到了一系列多點觸控,可是與識別器認識的手勢匹配失敗(識別不出來)。無響應方法。把手勢狀態的值從新置爲 UIGestureRecognizerStatePossible。
UIGestureRecognizerStateRecognized : 手勢識別器已經接收到了一系列多點觸控,而且識別器識別出該手勢。響應方法在下一個運行週期被調用,而且把手勢狀態的值從新置爲 UIGestureRecognizerStatePossible。
建立工程步驟請參照 實戰1中的前幾步。
在工程中建立一個 MyImageView 視圖類,繼承自 UIImageView。
首先爲咱們建立的視圖類進行初始化方法的編寫,在 MyImageView.m 文件中:
static int count; @implementation MyImageView { CGPoint previousLocation; UIPanGestureRecognizer *panGestureRecognizer; } #pragma mark - initialization - (id) initWithImage:(UIImage *)image { self = [super initWithImage:image]; if (self) { self.userInteractionEnabled = YES; // 在視圖被初始化的過程當中,建立一個 拖動手勢識別器 // 應用 target-action 模式,以該類爲目標對象,若是手勢被觸發,handlePan: 方法會被調用 panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; // 該類的實例對象可以被 拖動手勢識別器 所識別 self.gestureRecognizers = @[panGestureRecognizer]; } return self; } - (id) init { // 圖片文件的名稱爲 blue.png return [self initWithImage:[UIImage imageNamed:@"blue"]]; } #pragma mark - touches mothods are called // 當該類的實例對象被觸碰的時候,該方法會被觸發 - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.superview bringSubviewToFront:self]; // 視圖中心點 previousLocation = self.center; } #pragma mark - selector handlePan: - (void) handlePan:(UIPanGestureRecognizer *) gestureRecognizer { // print 該方法的運行次數 NSLog(@"%i", ++count); // 根據視圖的仿射變換來獲取偏移量 CGPoint translation = [gestureRecognizer translationInView:self.superview]; // 重置視圖中心點 self.center = CGPointMake(previousLocation.x + translation.x, previousLocation.y + translation.y); }
在 ViewController.m 文件中寫入代碼:
- (void)viewDidLoad { [super viewDidLoad]; // 建立類實例而且添加視圖 _myImageView = [[MyImageView alloc] initWithImage:[UIImage imageNamed:@"blue"]]; [self.view addSubview:_myImageView]; }
運行結果: 視圖可以響應拖動手勢,在屏幕上被拖動。控制檯顯示結果標明, handlePan: 方法在拖動手勢進行過程當中,一直都在被調用,直至手勢中止。
爲了讓自定義視圖可以響應手勢,咱們在建立而且初始化視圖類實例的時候,就應該建立響應的手勢識別器及其會響應的方法,當手勢在進行過程當中時,響應方法被反覆調用,直至手勢中止。爲了讓視圖可以跟隨手勢移動,咱們只需根據視圖先前的中心位置和被拖動之後的偏移位置來從新設定視圖的中心位置便可。
Jan 31, 2015