`
webdev2014
  • 浏览: 711436 次
文章分类
社区版块
存档分类
最新评论

IOS 触摸事件、手势识别讲解

 
阅读更多

13.1 事件概述

事件是当用户手指触击屏幕及在屏幕上移动时,系统不断发送给应用程序的对象。

系统将事件按照特定的路径传递给可以对其进行处理的对象。

在iOS中,一个UITouch对象表示一个触摸,一个UIEvent对象表示一个事件。事件对象中包含与当前多点触摸序列相对应的所有触摸对象,还可以提供与特定视图或窗口相关联的触摸对象。

响应者对象

响应者对象是可以响应事件并对其进行处理的对象。

UIResponder是所有响应者对象的基类,它不仅为事件处理,而且也为常见的响应者行为定义编程接口。

UIApplication、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。

第一响应者是应用程序中当前负责接收触摸事件的响应者对象(通常是一个UIView对象)。UIWindow对象以消息的形式将事件发送给第一响应者,使其有机会首先处理事件。如果第一响应者没有进行处理,系统就将事件(通过消息)传递给响应者链中的下一个响应者,看看它是否可以进行处理。

wps_clip_image-12891

响应者链

响应链是一个响应者对象的连接序列,事件或动作消息(或菜单编辑消息)依次传递。它允许响应者对象把事件处理的职责转交给其它更高层的对象。应用程序通过向上传递一个事件来查找合适的处理对象。因为点击检测视图也是一个响应者对象,应用程序在处理触摸事件时也可以利用响应链。响应链由一系列的下一个响应者组成。

wps_clip_image-22150

响应者链处理原则

1. 点击检测视图或者第一响应者传递事件或动作消息给它的视图控制器(如果它有的话);如果没有一个视图控制器,就传递给它的父视图。

2. 如果一个视图或者它的视图控制器不能处理这个事件或动作消息,它将传递给该视图的父视图。

3. 在这个视图层次中的每个后续的父视图遵循上述的模式,如果它不能处理这个事件或动作消息的话。

4. 最顶层的视图如果不能处理这个事件或动作消息,就传递给UIWindow对象来处理。

5. 如果UIWindow 对象不能处理,就传给单件应用程序对象UIApplication。

如果应用程序对象也不能处理这个事件或动作消息,将抛弃它。

13.2 触摸事件

触摸信息有时间和空间两方面,时间方面的信息称为阶段(phrase),表示触摸是否刚刚开始、是否正在移动或处于静止状态,以及何时结束—也就是手指何时从屏幕抬起。触摸信息还包括当前在视图或窗口中的位置信息,以及之前的位置信息(如果有的话)。当一个手指接触屏幕时,触摸就和某个窗口或视图关联在一起,这个关联在事件的整个生命周期都会得到维护。

触摸事件的阶段

wps_clip_image-20236

事件处理方法

在给定的触摸阶段中,如果发生新的触摸动作或已有的触摸动作发生变化,应用程序就会发送这些消息:

当一个或多个手指触碰屏幕时,发送touchesBegan:withEvent:消息。

当一个或多个手指在屏幕上移动时,发送touchesMoved:withEvent:消息。

当一个或多个手指离开屏幕时,发送touchesEnded:withEvent:消息。

当触摸序列被诸如电话呼入这样的系统事件所取消时,发送touchesCancelled:withEvent:消息。

触摸事件实例 EventInfo

#import <UIKit/UIKit.h>

@interface TouchView : UIView {
}
- (void)logTouchInfo:(UITouch *)touch;
@end

@implementation TouchView

- (void)logTouchInfo:(UITouch *)touch {
    CGPoint locInSelf = [touch locationInView:self];
    CGPoint locInWin = [touch locationInView:nil];
    NSLog(@"    touch.locationInView = {%2.3f, %2.3f}", locInSelf.x, locInSelf.y);
    NSLog(@"    touch.locationInWin = {%2.3f, %2.3f}", locInWin.x, locInWin.y);
    NSLog(@"    touch.phase = %d", touch.phase);
    NSLog(@"    touch.tapCount = %d", touch.tapCount);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesBegan - touch count = %d", [touches count]);
    for(UITouch *touch in event.allTouches) {
        [self logTouchInfo:touch];
    }
}

touch.phase,触摸事件的阶段。

touch.tapCount,触摸事件的轻碰次数,可以判断双击事件。

UIEvent 的allTouches方法,可以获得触摸点的集合,可以判断多点触摸事件。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesMoved - touch count = %d", [touches count]);
    for(UITouch *touch in event.allTouches) {
        [self logTouchInfo:touch];
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesEnded - touch count = %d", [touches count]);
    for(UITouch *touch in event.allTouches) {
        [self logTouchInfo:touch];
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesCancelled - touch count = %d", [touches count]);
    for(UITouch *touch in event.allTouches) {
        [self logTouchInfo:touch];
    }
}

13.3 手势

手势在iPhone中很重要,手势就是手触摸屏幕的方式。

单碰击

双碰击

多点触摸(合拢和展开)

轻抚

… …

单碰击和双碰击实例:MultiTap

单碰击为红色,双碰击为蓝色

#import <UIKit/UIKit.h>
@interface MultiTapView : UIView {
}
@end

#import "MultiTapView.h"


@implementation MultiTapView


- (void)turnBlue {
  self.backgroundColor = [UIColor blueColor];
}

- (void)turnRed {
  self.backgroundColor = [UIColor redColor];
}

//START:code.MultiTapView.touchesBegan:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  UITouch *touch = [touches anyObject];
  if(touch.tapCount == 2) {
      [[self class] cancelPreviousPerformRequestsWithTarget:self 
                                                 selector:@selector(turnRed) 
                                                   object:nil];
  }
}
//END:code.MultiTapView.touchesBegan:

//START:code.MultiTapView.touchesEnded:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  UITouch *touch = [touches anyObject];
  if(touch.tapCount == 1) {
      [self performSelector:@selector(turnRed) withObject:nil afterDelay:0.10f];
  }
  if(touch.tapCount == 2) {
      [self turnBlue];
  }
}
//END:code.MultiTapView.touchesEnded:

@end

[self performSelector:@selector(turnRed) withObject:nil afterDelay:0.10f]; 是在0.1秒后调用turnRed方法。

[[self class]cancelPreviousPerformRequestsWithTarget:self selector:@selector(turnRed) object:nil]; 是取消调用方法turnRed。

多点触摸(合拢和展开)PinchZoom

wps_clip_image-13471

PinchZoomView .h文件

复制代码
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface PinchZoomView : UIView {
    CALayer *robotLayer;
    CGFloat previousDistance;
    CGFloat zoomFactor;
    BOOL pinchZoom;
}

@property(nonatomic, retain) CALayer *robotLayer;

@end

m文件

#import "PinchZoomView.h"

@implementation PinchZoomView

@synthesize robotLayer;

- (void)awakeFromNib {
    self.robotLayer = [CALayer layer];
    UIImage *image = [UIImage imageNamed:@"Robot.png"];
    self.robotLayer.contents = (id)[image CGImage];
    self.robotLayer.bounds = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
    self.robotLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    [self.layer addSublayer:self.robotLayer];
    pinchZoom = NO;
    previousDistance = 0.0f;
    zoomFactor = 1.0f;
}

awakeFromNib当nib文件被加载的时候,加载器会发送一个awakeFromNib的消息到nib文件中的每个对象,每个对象都可以定义自己的 awakeFromNib方法来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象是执行awakeFromNib 。

robotLayer是 CALayer 对象,本例子中我们把图片对象添加到robotLayer对象中。使用 CALayer需要引入 <QuartzCore/QuartzCore.h>头文件和添加QuartzCore.framework框架。

//START:code.PinchZoomView.touchesBegan
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(event.allTouches.count == 2) {
        pinchZoom = YES;
        NSArray *touches = [event.allTouches allObjects];
        CGPoint pointOne = [[touches objectAtIndex:0] locationInView:self];
        CGPoint pointTwo = [[touches objectAtIndex:1] locationInView:self];
        previousDistance = sqrt(pow(pointOne.x - pointTwo.x, 2.0f) + 
                                pow(pointOne.y - pointTwo.y, 2.0f));
    } else {
        pinchZoom = NO;
    }
}
//END:code.PinchZoomView.touchesBegan

previousDistance 是获得两个点的距离。

pow是平方函数。

sqrt是开平方根函数。

wps_clip_image-12925

//START:code.PinchZoomView.touchesMoved
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if(YES == pinchZoom && event.allTouches.count == 2) {
        NSArray *touches = [event.allTouches allObjects];
        CGPoint pointOne = [[touches objectAtIndex:0] locationInView:self];
        CGPoint pointTwo = [[touches objectAtIndex:1] locationInView:self];
        CGFloat distance = sqrt(pow(pointOne.x - pointTwo.x, 2.0f) + 
                                pow(pointOne.y - pointTwo.y, 2.0f));
        zoomFactor += (distance - previousDistance) / previousDistance;
        zoomFactor = fabs(zoomFactor); 
        previousDistance = distance;
        self.robotLayer.transform = CATransform3DMakeScale(zoomFactor, zoomFactor, 1.0f);
    }
}
//END:code.PinchZoomView.touchesMoved

//START:code.PinchZoomView.touchesEnded
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if(event.allTouches.count != 2) {
        pinchZoom = NO;
        previousDistance = 0.0f;
    }
    if(event.allTouches.count == 1) {
//        NSArray *touches = [event.allTouches allObjects];
//        UITouch *touch = [touches objectAtIndex:0];
        UITouch *touch = [touches anyObject];
        NSInteger tapCount = [touch tapCount];
        if (tapCount == 2) {
            zoomFactor += 0.4;
            self.robotLayer.transform = CATransform3DMakeScale(zoomFactor, zoomFactor, 1.0f);
        } else if (tapCount == 3) {
            zoomFactor += 0.6;
            self.robotLayer.transform = CATransform3DMakeScale(zoomFactor, zoomFactor, 1.0f);
        } else if (tapCount == 4) {
            zoomFactor += 0.8;
            self.robotLayer.transform = CATransform3DMakeScale(zoomFactor, zoomFactor, 1.0f);
        }
    }
}
//END:code.PinchZoomView.touchesEnded

- (void)dealloc {
    self.robotLayer = nil;
    [robotLayer release];
    [super dealloc];
}

分享到:
评论

相关推荐

    IOS应用源码之ios触摸事件例子全集.rar

    这个压缩包"IOS应用源码之ios触摸事件例子全集.rar"显然是一个包含了各种iOS触摸事件处理的代码示例集合,对于学习iOS开发尤其是事件处理部分非常有帮助。以下将详细讲解iOS中的触摸事件及其相关知识点。 首先,iOS...

    简单手势识别实例(IOS5.0)

    本教程将详细讲解如何在UIViewController中使用简单手势识别,主要关注UIPanGestureRecognizer、UITapGestureRecognizer、UIPinchGestureRecognizer、UIRotationGestureRecognizer和UISwipeGestureRecognizer这五种...

    iOS开发之手势识别

    总结起来,手势识别极大地简化了iOS应用的触摸事件处理。通过使用UIGestureRecognizer及其子类,开发者可以轻松地实现各种用户交互,如点击、滑动、捏合等,从而提高应用的用户体验。了解并熟练运用这些手势识别技术...

    iOS TableView 添加手势方法

    对于TableView的情况,我们应该允许手势识别器处理除`UITableViewCellContentView`之外的触摸事件,因为`UITableViewCellContentView`是TableViewCell内部的视图,我们希望这些点击事件能被TableView识别并触发`...

    ios开发中手势多点触控实现

    本知识点将深入讲解如何在iOS应用中实现多点触控功能,主要涉及`UIGestureRecognizer`手势识别器和`touchesMoved`方法。 首先,`UIGestureRecognizer`是iOS SDK提供的一种抽象类,用于识别不同的触摸手势,如轻拍...

    移动软件开发-3期(KC015) 事件与手势识别 教学设计.doc

    在移动软件开发领域,特别是针对iOS系统的应用程序,事件与手势识别是不可或缺的一部分。iOS系统凭借其直观的触摸界面和丰富的手势支持,极大地提升了用户体验。这一章节主要探讨事件处理机制和手势识别技术,帮助...

    iOS开发之手势识别实例

    在iOS开发中,手势识别是实现用户交互的关键技术之一,它允许用户通过触摸屏幕的不同方式与应用程序进行互动。本文将详细讲解如何在iOS应用中实现手势识别,包括使用Storyboard和纯代码的方式。 首先,iOS提供了...

    IOS手势锁屏

    总的来说,实现iOS手势锁屏功能需要综合运用多种技术,包括手势识别、图形编程、触摸事件处理、状态管理、动画效果以及数据存储。开发者需要对iOS SDK有深入理解,才能创造出流畅且安全的手势解锁体验。

    手势识别器之敲击

    在iOS开发中,手势识别器(Gesture Recognizer)是苹果提供的一个强大工具,它使得用户可以通过各种触摸操作与应用程序进行交互。"手势识别器之敲击"是一个典型的iOS开发示例,专注于讲解如何实现敲击(Tap Gesture...

    IOS手势示例

    在iOS开发中,手势识别(Gesture Recognizer)是构建用户交互界面的重要组成部分。手势示例通常涵盖了一系列常见的触摸操作,使应用程序能够响应用户的直观输入。本篇将详细讲解标题为"IOS手势示例"的代码所展示的...

    ios事件简单Demo

    在这个Demo中,开发者可能会涉及触摸事件、滚动事件以及手势识别等核心概念。下面将详细讲解这些知识点。 1. 触摸事件(TouchEvent): iOS中的触摸事件主要包括三种类型:`UIEventSubtypeTouchesBegan`、`...

    IOS 滑动手势

    首先,你需要了解iOS中的手势识别器(Gesture Recognizer)。在iOS SDK中,UIPanGestureRecognizer类是用来检测平移(pan)、滑动(swipe)等连续的手势。滑动手势分为左滑、右滑、上滑和下滑四种,每种都有其特定的...

    IOS的处理touch事件(依照手指的移动移动一个圆,开发环境用的ios7,storyboard)

    本文将详细讲解如何在iOS环境中,尤其是使用iOS 7和Storyboard的情况下,处理触摸事件来实现根据手指移动来移动一个圆形视图。 首先,我们需要了解iOS中的触摸事件类型。iOS提供三种基本的触摸事件:`touchesBegan:...

    IOS 手势锁屏

    手势锁屏是基于触摸屏设备的多点触控技术,用户在预设的解锁区域内绘制特定的轨迹,系统会记录并识别这个轨迹作为解锁密码。当用户在屏幕上再次绘制相同的轨迹时,设备将解锁。这种解锁方式相比传统密码更难以被他人...

    IOS开发之手势响应事件优先级的实例详解

    在iOS开发中,手势识别(Gesture Recognizers)是构建用户界面不可或缺的一部分,它们使得用户可以通过触摸屏幕的不同方式与应用进行交互。手势响应事件优先级的管理对于解决不同手势间的冲突至关重要,确保应用能够...

    ios 手势解锁实现

    总之,实现一个iOS手势解锁功能涉及了手势识别、路径绘制、匹配判断等多个环节,需要巧妙地结合Objective-C的UIKit框架和编程技巧。通过"GesturePass"项目,开发者不仅可以学习到具体实现,还能提升自己在手势识别和...

    iOS 开发 - 手绘的简单实现

    iOS设备上的触摸事件是由UIResponder链来处理的,特别是对于UIView对象,它们可以接收并处理用户的触摸事件。当用户在屏幕上触摸或滑动时,系统会发送`touchesBegan:withEvent:`、`touchesMoved:withEvent:`和`...

    Event Handling Guide for iOS

    在iOS中,事件模型基于Cocoa Touch框架,其主要由三个组件构成:事件(Events)、事件响应者链(Event Responder Chain)和手势识别器(Gesture Recognizers)。 1. **事件**:iOS中的事件分为不同类型,例如触摸...

    ios-手势解锁,可以添加到应用中的手势解锁.zip

    本教程将基于提供的"ios-手势解锁,可以添加到应用中的手势解锁.zip"文件,讲解如何在你的应用中实现一个类似九宫格的手势解锁功能。 首先,我们要了解手势解锁的核心组件——`UIPanGestureRecognizer`。它是UIKit...

    多手势操作实现ios图文混排

    // 如果触摸点在UILabel范围内,允许手势识别 if ([self.label containsPoint:[touch locationInView:self.label]]) { return YES; } return NO; } - (void)handleTap:(UITapGestureRecognizer *)sender { //...

Global site tag (gtag.js) - Google Analytics