`
啸笑天
  • 浏览: 3461263 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

iOS 手势及触摸

 
阅读更多

一、响应链

在IOS开发中会遇到各种操作事件,通过程序可以对这些事件做出响应。

首先,当发生事件响应时,必须知道由谁来响应事件。在IOS中,由响应者链来对事件进行响应,所有事件响应的类都是UIResponder的子类,响应者链是一个由不同对象组成的层次结构,其中的每个对象将依次获得响应事件消息的机会。当发生事件时,事件首先被发送给第一响应者,第一响应者往往是事件发生的视图,也就是用户触摸屏幕的地方。事件将沿着响应者链一直向下传递,直到被接受并做出处理。一般来说,第一响应者是个视图对象或者其子类对象,当其被触摸后事件被交由它处理,如果它不处理,事件就会被传递给它的视图控制器对象viewcontroller(如果存在),然后是它的父视图(superview)对象(如果存在),以此类推,直到顶层视图。接下来会沿着顶层视图(top view)到窗口(UIWindow对象)再到程序(UIApplication对象),如果UIApplication也不响应,那么还有一个地方可以构建一个全局响应者作为响应链的最后一个环节,那就是应用程序的委托,前提是他是UIResponder的子类。如果整个过程都没有响应这个事件,该事件就被丢弃。一般情况下,在响应者链中只要由对象处理事件,事件就停止传递。

一个典型的相应路线图如:

First Responser -- > The Window -- >The Application -- > App Delegate

正常的响应者链流程经常被委托(delegation)打断,一个对象(通常是视图)可能将响应工作委托给另一个对象来完成(通常是视图控制器ViewController),这就是为什么做事件响应时在ViewController中必须实现相应协议来实现事件委托。在iOS中,存在UIResponder类,它定义了响应者对象的所有方法。UIApplication、UIView等类都继承了UIResponder类,UIWindow和UIKit中的控件因为继承了UIView,所以也间接继承了UIResponder类,这些类的实例都可以当作响应者。

 

管理事件分发

视图对触摸事件是否需要作处回应可以通过设置视图的userInteractionEnabled属性。默认状态为YES,如果设置为NO,可以阻止视图接收和分发触摸事件。除此之外,当视图被隐藏(setHidden:YES)或者透明(alpha值为0)也不会收事件。不过这个属性只对视图有效,如果想要整个程序都步响应事件,可以调用UIApplication的beginIngnoringInteractionEvents方法来完全停止事件接收和分发。通过endIngnoringInteractionEvents方法来恢复让程序接收和分发事件。

如果要让视图接收多点触摸,需要设置它的multipleTouchEnabled属性为YES,默认状态下这个属性值为NO,即视图默认不接收多点触摸。

 

二、触摸

iPhone中处理触摸屏的操作,在3.2之前是主要使用的是由UIResponder提供的如下4种方式:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event  //手指触摸屏幕时报告UITouchPhaseBegan事件

 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event   //在手指在屏幕上移动时报告UITouchPhaseMoved事件

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event   //在手指离开屏幕时报告UITouchPhaseEnded事件

 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event    //在因接听电话或其他因素导致取消触摸时报告UITouchPhaseCancelled事件

属性:

——UITouch

UITouch对象是一个手指接触到屏幕并在屏幕上移动或离开屏幕时创建的。它有几个属性和实例方法:

phase:属性,返回一个阶段常量,指出触摸开始、继续、结束或被取消,是一个枚举配型,包含了

·UITouchPhaseBegan(触摸开始)

·UITouchPhaseMoved(接触点移动)

·UITouchPhaseStationary(接触点无移动)

·UITouchPhaseEnded(触摸结束)

·UITouchPhaseCancelled(触摸取消)

tapCount:属性,轻按屏幕的次数

timeStamp:属性,触摸发生的时间

view:属性,触摸始于那个视图

window:属性,触摸始于哪个窗口

lacationInView:方法,触摸在指定视图中的当前位置

previousLocationView:方法,触摸在指定视图中的前一个位置

——UIEvent

UIEvent对象包含一组相关的UITouch对象,由UITouch对象组成UIEvent对象,可以理解成一个完整的触摸操作是一个UIEvent,而这一系列完整操作中的每个点就是UITouch(按下、移动、离开)。

UIEvent的作用是提供相关触摸操作的列表,如果要获取在屏幕上触摸的手势,可以使用该对象,这一些列操作都存储在Foundation框架中的NSSet对象中。

 

但是这种方式甄别不同的手势操作实在是麻烦,需要你自己计算做不同的手势分辨。后来。。。

苹果就给出了一个比较简便的方式,就是使用UIGestureRecognizer。

三、UIGestureRecognizer

UIGestureRecognizer基类是一个抽象类,我们主要是使用它的子类(名字包含链接,可以点击跳到ios Developer library,看官方文档):

UITapGestureRecognizer

UIPinchGestureRecognizer

UIRotationGestureRecognizer

UISwipeGestureRecognizer

UIPanGestureRecognizer

UILongPressGestureRecognizer

从名字上我们就能知道, Tap(点击)、Pinch(捏合)、Rotation(旋转)、Swipe(滑动,快速移动,是用于监测滑动的方向的)、Pan (拖移,慢速移动,是用于监测偏移的量的)以及 LongPress(长按)。

举个例子,可以在viewDidLoad函数里面添加:

[cpp] view plaincopyprint?

-(void) viewDidLoad  

{  

 [super viewDidLoad];  

 // Do any additional setup after loading the view from its nib.  

 UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];  

 [self.view addGestureRecognizer:panRecognizer];//关键语句,给self.view添加一个手势监测;  

 panRecognizer.maximumNumberOfTouches = 1;  

 panRecognizer.delegate = self;  

 [panRecognizer release];  

}  

其它手势方法类似。

其核心就是设置delegate和在需要手势监测的view上使用addGestureRecognizer添加指定的手势监测。

当然要记得在作为delegate的view的头文件加上<UIGestureRecognizerDelegate>。

不过有些手势是关联的,怎么办呢?例如 Tap 与 LongPress、Swipe与 Pan,或是 Tap 一次与Tap 兩次。

手势识别是具有互斥的原则的,比如单击和双击,如果它识别出一种手势,其后的手势将不被识别。所以对于关联手势,要做特殊处理以帮助程序甄别,应该把当前手势归结到哪一类手势里面。

比如,单击和双击并存时,如果不做处理,它就只能发送出单击的消息。为了能够识别出双击手势,就需要做一个特殊处理逻辑,即先判断手势是否是双击,在双击失效的情况下作为单击手势处理。使用

[A requireGestureRecognizerToFail:B]函数,它可以指定当A手势发生时,即便A已经滿足条件了,也不会立刻触发,会等到指定的手势B确定失败之后才触发。

[cpp] view plaincopyprint?

- (void)viewDidLoad   

{  

    // 单击的 Recognizer  

    UITapGestureRecognizer* singleRecognizer;  

    singleRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(SingleTap:)];  

    //点击的次数  

    singleTapRecognizer.numberOfTapsRequired = 1; // 单击  

  

    //给self.view添加一个手势监测;  

  

  [self.view addGestureRecognizer:singleRecognizer];  

  

    

    // 双击的 Recognizer  

    UITapGestureRecognizer* double;  

    doubleRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(DoubleTap:)];  

    doubleTapRecognizer.numberOfTapsRequired = 2; // 双击  

    //关键语句,给self.view添加一个手势监测;  

    [self.view addGestureRecognizer:doubleRecognizer];  

      

    // 关键在这一行,双击手势确定监测失败才会触发单击手势的相应操作  

    [singleRecognizer requireGestureRecognizerToFail:doubleRecognizer];  

    [singleRecognizer release];  

    [doubleRecognizer release];  

}  

  

-(void)SingleTap:(UITapGestureRecognizer*)recognizer  

{  

//处理单击操作  

}  

  

-(void)DoubleTap:(UITapGestureRecognizer*)recognizer  

{  

//处理双击操作  

}  

四、iphone操作手势的大概种类

1.点击(Tap)

点击作为最常用手势,用于按下或选择一个控件或条目(类似于普通的鼠标点击)、

2.拖动(Drag)

拖动用于实现一些页面的滚动,以及对控件的移动功能。

3.滑动(Flick)

滑动用于实现页面的快速滚动和翻页的功能。

4.横扫(Swipe)

横扫手势用于激活列表项的快捷操作菜单

5.双击(Double Tap)

双击放大并居中显示图片,或恢复原大小(如果当前已经放大)。同时,双击能够激活针对文字编辑菜单。

6.放大(Pinch open)

放大手势可以实现以下功能:打开订阅源,打开文章的详情。在照片查看的时候,放大手势也可实现放大图片的功能。

7.缩小(Pinch close)

缩小手势,可以实现与放大手势相反且对应的功能的功能:关闭订阅源退出到首页,关闭文章退出至索引页。在照片查看的时候,缩小手势也可实现缩小图片的功能。

8.长按(Touch &Hold)

在我的订阅页,长按订阅源将自动进入编辑模式,同时选中手指当前按下的订阅源。这时可直接拖动订阅源移动位置。

针对文字长按,将出现放大镜辅助功能。松开后,则出现编辑菜单。

针对图片长按,将出现编辑菜单。

9.摇晃(Shake)

摇晃手势,将出现撤销与重做菜单。主要是针对用户文本输入的。

 

五、通过消息响应者链找到UIView所在的UIViewController 

@interface UIView (FirstViewController)

 

- (UIViewController *) firstViewController;

- (id) traverseResponderChainForUIViewController;

 

@end

 

@implementation UIView (FirstViewController)

 

- (UIViewController *) firstViewController {

    // convenience function for casting and to "mask" the recursive function

    return (UIViewController *)[self traverseResponderChainForUIViewController];

}

 

- (id) traverseResponderChainForUIViewController {

    id nextResponder = [self nextResponder];

    if ([nextResponder isKindOfClass:[UIViewController class]]) {

        return nextResponder;

    } else if ([nextResponder isKindOfClass:[UIView class]]) {

        return [nextResponder traverseResponderChainForUIViewController];

    } else {

        return nil;

    }

}

六、事件传递

当一个子view需要接收点击事件,其父view也需要接收点击事件,该如何处理:

按照正常情况下,子类接收点击事件以后,事件不会主动传递到下一个响应者,因此父类便不再接收点击事件。如果子类不处理点击事件,则事件会一直传递下去,直到UIApplication。

但是我们可以使得子类处理过响应事件后仍将响应这传递到下一个响应者。但是我们编写代码才能办到。

子view的代码如下:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

// 这里可以做子view自己想做的事,做完后,事件继续上传,就可以让其父类,甚至父viewcontroller获取到这个事件了

   [[selfnextResponder]touchesBegan:toucheswithEvent:event];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

  [[selfnextResponder]touchesEnded:toucheswithEvent:event];

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {

  [[selfnextResponder] touchesCancelled:toucheswithEvent:event];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

  [[selfnextResponder] touchesMoved:toucheswithEvent:event];

}

 

 

分享到:
评论
1 楼 啸笑天 2016-03-10  
/**

*  本节介绍tap的3个弄不太林清并且容易混淆的属性:

   cancelsTouchesInView/delaysTouchesBegan/delaysTouchesEnded

*   (0)首先要知道的是

        1.这3个属性是作用于GestureRecognizers(手势识别)与触摸事件之间联系的属性。实际应用中好像很少会把它们放到一起,大多都只是运用手势识别,所以这3个属性应该很少会用到。

        2.对于触摸事件,window只会有一个控件来接收touch。这个控件是首先接触到touch的并且重写了触摸事件方法(一个即可)的控件

        3.手势识别和触摸事件是两个独立的事,只是可以通过这3个属性互相影响,不要混淆。

*  (1)在默认情况下(即这3个属性都处于默认值的情况下),如果触摸window,首先由window上最先符合条件的控件(该控件记为hit-test view)接收到该touch并触发触摸事件touchesBegan。同时如果某个控件的手势识别器接收到了该touch,就会进行识别。手势识别成功之后发送触摸事件touchesCancelled给hit-testview,hit-test view不再响应touch。



* (2)cancelsTouchesInView:

    默认为YES,这种情况下当手势识别器识别到touch之后,会发送touchesCancelled给hit-testview以取消hit-test view对touch的响应,这个时候只有手势识别器响应touch。

    当设置成NO时,手势识别器识别到touch之后不会发送touchesCancelled给hit-test,这个时候手势识别器和hit-test view均响应touch。



* (3)delaysTouchesBegan:

    默认是NO,这种情况下当发生一个touch时,手势识别器先捕捉到到touch,然后发给hit-testview,两者各自做出响应。如果设置为YES,手势识别器在识别的过程中(注意是识别过程),不会将touch发给hit-test view,即hit-testview不会有任何触摸事件。只有在识别失败之后才会将touch发给hit-testview,这种情况下hit-test view的响应会延迟约0.15ms。



* (4)delaysTouchesEnded:

    默认为YES。这种情况下发生一个touch时,在手势识别成功后,发送给touchesCancelled消息给hit-testview,手势识别失败时,会延迟大概0.15ms,期间没有接收到别的touch才会发送touchesEnded。如果设置为NO,则不会延迟,即会立即发送touchesEnded以结束当前触摸。

*/

相关推荐

    iOS 开发 手势与触摸事件

    在iOS开发中,手势识别(Gesture Recognizers)和触摸事件(Touch Events)是构建用户交互界面不可或缺的部分。这些技术使得应用程序能够对用户的屏幕操作做出响应,从而提供更加自然和直观的用户体验。本教程将深入...

    ios手势和触摸代码完整版.7z

    这份"ios手势和触摸代码完整版.7z"资源很可能是包含了实现这些功能的各种示例代码,帮助开发者深入理解和实践。 首先,我们要了解iOS中的基本触摸事件。iOS设备的屏幕可以检测到多个触摸点,这些触摸事件主要分为...

    ios-触摸手势 - demo.zip

    对于新手来说,这是一个很好的学习资源,可以加深对iOS手势交互的理解,提升开发技能。在实践中,记得结合MVC(Model-View-Controller)设计模式,将手势逻辑适当地分离到合适的层面上,以保持代码的清晰和可维护性...

    iOS手势(全)

    在iPhone X及后续机型中,从屏幕底部向上滑动可以打开控制中心,而在旧版iOS系统中,上滑常用于返回主屏幕。 10. **下滑(Swipe Down)**: 从屏幕顶部下滑可以访问通知中心,而在全屏应用中,这个手势通常用于...

    IOS手势解锁

    **iOS手势解锁详解** 在iOS操作系统中,手势解锁是一种安全且直观的设备解锁方式,它允许用户通过在触摸屏上绘制特定的图案来解锁设备。本文将深入探讨iOS手势解锁的功能、工作原理以及如何实现这一功能。 ### 一...

    IOS应用源码之手势和触摸 .rar

    本资源包“IOS应用源码之手势和触摸 .rar”包含了关于iOS手势识别和触摸事件处理的示例代码,这对于理解并熟练运用这些技术非常有帮助。 一、手势识别(GestureRecognizer) 手势识别是iOS SDK中的一个关键特性,...

    IOS应用源码Demo-手势和触摸-毕设学习.zip

    在iOS应用开发中,手势和触摸是至关重要的组成部分,它们为用户提供直观的交互方式,使得应用程序更加生动和用户友好。这个“IOS应用源码Demo-手势和触摸-毕设学习.zip”压缩包显然包含了用于毕业设计学习的源代码...

    ios手势图形解锁完整Demo

    本Demo,"ios手势图形解锁完整Demo",提供了一个实现这一功能的实例,使得开发者可以快速理解和应用这种技术。 一、手势图形解锁原理 手势图形解锁的核心原理是利用触摸屏设备的多点触控能力,记录用户在预设画布上...

    iOS手势集合

    iOS手势主要包括基本手势、复合手势以及自定义手势。 1. 基本手势: - `UIPanGestureRecognizer`: 平移手势,用于检测用户在屏幕上进行的平移操作。 - `UIPinchGestureRecognizer`: 捏合手势,用于识别用户的手指...

    ios手势操作演示

    本项目"ios手势操作演示"是一个使用Swift编写的示例,旨在帮助开发者理解和应用iOS中的手势识别技术。 Swift是Apple为iOS、macOS、watchOS和tvOS平台推出的一种强大且易学的编程语言,它具有现代编程语言的特点,如...

    仿IOS界面手势切换

    5. **触摸事件分发**:为了处理手势切换与应用其他组件的交互,开发者需要正确地处理触摸事件的分发。这可能涉及到ViewGroup的onInterceptTouchEvent和onTouchEvent方法,确保手势识别不会影响到其他子视图的正常...

    ios应用源码之手势和触摸 2018128

    在iOS应用开发中,手势(Gesture Recognizers)和触摸(Touch Events)是用户界面交互的核心组成部分,它们使得用户可以通过屏幕上的各种操作与应用程序进行互动。本资料“ios应用源码之手势和触摸 2018128”很可能...

    IOS应用源码——手势和触摸.zip

    4. 拖拽手势(Drag & Drop Gesture):用户可以拖动一个视图并将其放置在其他位置,iOS 11及以上版本支持更高级的拖放功能。 5. 长按手势(Long Press Gesture):检测用户在屏幕上持续按压的时间,可用于显示上下文...

    iOS手势返回上一级

    总的来说,“iOS手势返回上一级”是iOS用户体验的关键组成部分,开发者需要充分理解和掌握其工作原理,以便在应用中实现高效、流畅的导航。通过自定义和优化手势,可以进一步提升应用的用户满意度。

    IOS应用源码——手势和触摸.rar

    在iOS开发中,手势(Gestures)和触摸(Touches)是用户与应用程序交互的核心机制。这个名为"手势和触摸"的源码压缩包很可能是为了帮助开发者深入了解并实践这两种技术。下面,我们将深入探讨iOS中的手势识别和触摸...

    touch手势与触摸

    4. 触摸手势识别:许多系统提供了内置的手势识别,如iOS的`UIGestureRecognizer`类,包括`UITapGestureRecognizer`(点击)、`UIPanGestureRecognizer`(拖动)、`UISwipeGestureRecognizer`(滑动)等。开发者可以...

    ios手势程序

    在这个"ios手势程序"中,我们将会探讨以下几个基本的手势实现: 1. **轻扫(Swipe)手势**: 文件名:`DroppableView_10826.zip` 轻扫手势允许用户通过快速滑动手指来触发特定的事件。在iOS中,有两种主要类型的...

    IOS 手势锁屏

    本文将深入探讨iOS手势锁屏的相关知识点。 首先,我们要了解手势解锁的工作原理。手势锁屏是基于触摸屏设备的多点触控技术,用户在预设的解锁区域内绘制特定的轨迹,系统会记录并识别这个轨迹作为解锁密码。当用户...

Global site tag (gtag.js) - Google Analytics