iOS開發學習之觸摸事件和手勢識別

來源:互聯網
上載者:User

iOS的輸入事件觸摸事件手勢識別手機搖晃一、iOS的輸入事件 觸摸事件(滑動、點擊)運動事件(搖一搖、手機傾斜、行走),不需要人為參與的遠端控制事件(耳機控制手機聲音)1⃣️iOS事件對象都是UIEvent類的執行個體UIEvent類對事件類型定義了enum常量:typedef NS_ENUM(NSInteger, UIEventType){     UIEventTypeTouches,     UIEventTypeMotion,     UIEventRemoteControl,};觸摸事件必須是繼承UIResponser的二、觸摸事件1⃣️UIView,有4種處理不同的觸摸事件UIView是UIResponder的子類,可以覆蓋下列4個方法處理不同的觸摸事件。1. 一根或者多根手指開始觸控螢幕幕- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event2.一根或者多根手指在螢幕上移動(隨著手指的移動,會持續調用該方法)- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event3.一根或者多根手指離開螢幕- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event4.觸摸結束前,某個系統事件(例如電話呼入)會打斷觸摸過程- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event複製代碼#pragma mark - UITouch事件#pragma mark 觸摸開始- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    NSLog(@"觸摸開始");    for (UITouch *touch in touches) {        NSLog(@"%@", touch);    }} #pragma mark 觸摸移動- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{    NSLog(@"觸摸移動Touch對象個數:%d",[touches count]);    // 要移動介面上黃顏色的視圖        // 1. 得到當前手指的位置    UITouch *touch = [touches anyObject];    CGPoint location = [touch locationInView:self.view];    // 2. 得到上一次手指的位置    CGPoint preLocation = [touch previousLocationInView:self.view];    // 3. 計算兩個位置之間的位移    CGPoint offset = CGPointMake(location.x - preLocation.x, location.y - preLocation.y);    // 4. 使用計算出來的位移量,調整視圖的位置    [_demoView setCenter:CGPointMake(_demoView.center.x + offset.x, _demoView.center.y + offset.y)];        // 完整的UITouch事件調試方法    NSLog(@"觸摸移動");    for (UITouch *touch in touches) {        NSLog(@"%@", touch);    }} #pragma mark 觸摸結束- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{    // 完整的UITouch事件調試方法    NSLog(@"觸摸完成");    for (UITouch *touch in touches) {        NSLog(@"%@", touch);    }} #pragma mark 觸摸中斷- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{    // 完整的UITouch事件調試方法    NSLog(@"觸摸中斷");    for (UITouch *touch in touches) {        NSLog(@"%@", touch);    }}複製代碼2⃣️觸摸事件的處理如果hit-test視圖無法處理事件,則通過響應者鏈向上傳遞1.如果hit-test視圖的控制器存在,就傳遞給控制器;如果控制器不存在,則將其傳遞給它的父視圖2.如果視圖或它的控制器無法處理收到的事件或訊息,則將其傳遞給該視圖的父視圖3.每一個在視圖繼承樹中的上層視圖如果不能處理收到的事件或訊息,則重複上面的步驟1,24.在視圖繼承樹的最上層視圖,如果也不能處理收到的事件或訊息,則其將事件或訊息傳遞給視窗對象進行處理5. 如果視窗對象也不能進行處理,則其將事件或訊息傳遞給UIApplication對象6.如果UIApplication也不能處理該事件或訊息,則將其丟棄當使用者點擊螢幕時,會產生一個UITouch對象傳遞給UIApplication,然後由window負責尋找最適合相應觸摸事件的視圖對象(hitTest,pointInside)找到合適的視圖之後,Touch方法由對應的視圖完成,上級視圖不再接管3⃣️不接受處理事件的三種方法不接收使用者互動:userInteractionEnabled = NO;隱藏:hidden = YES;透明:alpha = 0~0.01三、手勢識別1⃣️iOS目前支援的手勢識別(6種)UITapGestureRecognizer(點按)UIPinchGestureRecognizer(捏合)UIPanGestureRecognizer(拖動)UISwipeGestureRecognizer(輕掃)UIRotationGestureRecognizer(旋轉)UILongPressGestureRecognizer(長按)2⃣️手勢識別的使用方法(4步)通常在視圖載入的時候定義(UIGestureRecognizer是抽象類別,需要執行個體化使用)建立手勢識別執行個體設定手勢識別屬性,例如手指數量,方向等將手勢識別附加到指定的視圖之上編寫手勢觸發回應程式法3⃣️手勢識別的狀態(7個)   1.  // 沒有觸摸事件發生,所有手勢識別的預設狀態    UIGestureRecognizerStatePossible,    // 一個手勢已經開始但尚未改變或者完成時    UIGestureRecognizerStateBegan,    // 手勢狀態改變    UIGestureRecognizerStateChanged,    // 手勢完成    UIGestureRecognizerStateEnded,    // 手勢取消,恢複至Possible狀態    UIGestureRecognizerStateCancelled,     // 手勢失敗,恢複至Possible狀態    UIGestureRecognizerStateFailed,    // 識別到手勢識別    UIGestureRecognizerStateRecognized =UIGestureRecognizerStateEnded   2.手勢識別的屬性state——手勢狀態view——手勢發生視圖常用方法locationInView 獲得手勢發生對應視圖所在位置複製代碼- (void)viewDidLoad{    [super viewDidLoad];    /**     1. 示範點按手勢     */    // 根據執行個體化方法,我們知道:    // 1.有一個處理訊息的對象,應該是self    // 2.我們需要定義一個方法,當手勢識別檢測到的時候,運行    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction:)];    // setNumberOfTapsRequired 點按次數    [tap setNumberOfTapsRequired:1];    // setNumberOfTouchesRequired 點按的手指數量    [tap setNumberOfTouchesRequired:1];    // 把手勢識別增加到視圖上    [self.demoView addGestureRecognizer:tap];        /**     2. 捏合點按手勢     */    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinchAction:)];    [self.demoView addGestureRecognizer:pinch];        /**     3. 旋轉點按手勢     */    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotationAction:)];    [self.demoView addGestureRecognizer:rotation];        /**     4. 拖放點按手勢     */    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)];    [self.demoView addGestureRecognizer:pan];        /**     5. 長按手勢     */    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressAction:)];    [self.demoView addGestureRecognizer:longPress];        /**     6. 撥動手勢     關於撥動手勢,是需要指定方向的,如果你不指定方向,那麼只能接收到的向右方向的輕掃事件     */    // 向左掃    UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];    [swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];    [self.view addGestureRecognizer:swipeLeft];    // 向右掃    UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];    [swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];    [self.view addGestureRecognizer:swipeRight];    // 向上掃    UISwipeGestureRecognizer *swipeTop = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];    [swipeTop setDirection:UISwipeGestureRecognizerDirectionUp];    [self.view addGestureRecognizer:swipeTop];    // 向下掃    UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];    [swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];    [self.view addGestureRecognizer:swipeDown];} - (void)didReceiveMemoryWarning{    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.} #pragma mark - 撥動手勢- (void)swipeAction:(UISwipeGestureRecognizer *)sender{    NSLog(@"%d", sender.direction);    switch (sender.direction) {        case UISwipeGestureRecognizerDirectionLeft:            NSLog(@"向左掃");            break;        case UISwipeGestureRecognizerDirectionRight:            NSLog(@"向右掃");            break;        case UISwipeGestureRecognizerDirectionUp:            NSLog(@"向上掃");            break;        case UISwipeGestureRecognizerDirectionDown:            NSLog(@"向下掃");            break;        default:            break;    }} #pragma mark - 長按手勢- (void)longPressAction:(UILongPressGestureRecognizer *)sender{    // 我們可以利用demoView的Tag屬性,預設時tag=0    // 如果tag=0,我們放大一倍,否則,我們縮小一半    CGFloat scale;    if (_demoView.tag == 0) {        scale = 2.0;        _demoView.tag = 1;    } else {        scale = 0.5;        _demoView.tag = 0;    }        sender.view.transform = CGAffineTransformScale(sender.view.transform, scale, scale);} #pragma mark - 拖放手勢- (void)panAction:(UIPanGestureRecognizer *)sender{    // 在拖放手勢中是需要考慮手指的狀態的UIGestureRecognizerState    // 在拖放手勢中使用的狀態是UIGestureRecognizerStateChanged    // 通常在使用拖放手勢的時候,當手指離開的時候,應該做一個很小的動作,提醒使用者拖放完成    if (sender.state == UIGestureRecognizerStateChanged) {        // locationInView        [_demoView setCenter:[sender locationInView:self.view]];    } else if (sender.state == UIGestureRecognizerStateEnded) {        [_demoView setBackgroundColor:[UIColor yellowColor]];    }} #pragma mark - 旋轉手勢- (void)rotationAction:(UIRotationGestureRecognizer *)sender{    sender.view.transform = CGAffineTransformRotate(sender.view.transform, sender.rotation);        // 和捏合操作類似,旋轉角度同樣需要方福偉    sender.rotation = 0.0f;} #pragma mark - 捏合手勢- (void)pinchAction:(UIPinchGestureRecognizer *)sender{    // 有關轉換的內容,我們在後續動畫部分再繼續    sender.view.transform = CGAffineTransformScale(sender.view.transform, sender.scale, sender.scale);        // 縮放功能很簡單,但是不要忘記將比例複位    sender.scale = 1.0f;    NSLog(@"捏我了");} #pragma mark - 點按手勢- (void)tapAction:(UITapGestureRecognizer *)sender{    /**     在開發過程中,如果沒有什麼必要,最好不要對一個UI控制項,既使用觸摸,又使用手勢。     */    NSLog(@"點我了 %@", sender);} #pragma mark - 手勢觸摸事件- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    NSLog(@"觸摸事件!");    // 1. 先取出UITouch對象    // 2. 判斷響應點擊的UIView是不是我們需要的    UITouch *touch = [touches anyObject];    if ([touch view] == _imageView) {        NSLog(@"點到映像了!");    }}複製代碼四、手機搖晃1. 建立搖晃監聽視圖ShakeListenerView,並且設定canBecomeFirstResponder返回YES- (BOOL)canBecomeFirstResponder{    return YES;}2. 在Storyboard中將ViewController的View的Class設定為:ShakeListenerView3. 在ViewController.m檔案中增加:viewDidAppear和viewDidDisappear在視圖出現和消失時成為/撤銷第一響應者身份4. 在視圖控制器中增加手勢監聽方法:- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{    if (event.subtype == UIEventSubtypeMotionShake) {        NSLog(@"shake phone");    }}複製代碼#pragma mark - 要讓ViewController支援搖晃,需要寫三個方法// 1. 成為第一響應者,視圖一出現時,就應該成為第一響應者- (void)viewDidAppear:(BOOL)animated{    [self.view becomeFirstResponder];    // 不要忘記去實現父類方法    [super viewDidAppear:animated];} // 2. 登出第一響應者,視圖要關閉的時候,登出- (void)viewDidDisappear:(BOOL)animated{    [self.view resignFirstResponder];    // 不要忘記去實現父類方法    [super viewDidDisappear:animated];} // 3. 監聽並處理移動事件,判斷是否搖晃了手機- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{    if (motion == UIEventSubtypeMotionShake) {        NSLog(@"搖啊搖,搖到外婆橋!!!");    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.