iOS-控件响应用户控制事件之事件处理
事件处理
响应者对象
在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。我们称之为“响应者对象”
UIApplication、UIViewController、UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件
UIResponder内部提供了以下方法来处理事件
- 这些类可以覆盖下列几个方法处理不同的触摸事件 ```objc //触摸事件
- (void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event;
- (void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event;
- (void)touchesEnded:(NSSet )touches withEvent:(UIEvent )event;
- (void)touchesCancelled:(NSSet )touches withEvent:(UIEvent )event;
//加速计事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
//远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event; ```
事件的参数
UITouch
UITouch的作用
- 保存着跟手指相关的信息,比如触摸的位置、时间、阶段
- 当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在的触摸位置
- 当手指离开屏幕时,系统会销毁相应的UITouch对象
UITouch的方法
- (CGPoint)locationInView:(UIView *)view;
- 返回值表示触摸在view上的位置
- 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0))
- 调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
- (CGPoint)previousLocationInView:(UIView *)view;
- 该方法记录了前一个触摸点的位置
UIEvent
- 每产生一个事件,就会产生一个UIEvent对象
- UIEvent:称为事件对象,记录事件产生的时刻和类型
常见属性
事件类型
@property(nonatomic,readonly) UIEventType type;
@property(nonatomic,readonly) UIEventSubtype subtype;
事件产生的时间
@property(nonatomic,readonly) NSTimeInterval timestamp;
事件的产生和传递
- 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中。
- 2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)
- 3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步
- 4.找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理
touchesBegan…
touchesMoved…
touchedEnded…
如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件(掌握)
如何找到最合适的控件来处理事件?
- 自己是否能接收触摸事件?
- 触摸点是否在自己身上?
- 从后往前遍历子控件,重复前面的两个步骤
- 如果没有符合条件的子控件,那么就自己最适合处理
原理
// point:是方法调用者坐标系上的触摸点的位置
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// 1.判断下能否接收触摸事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.0) return nil;
// 2.判断下点在不在控件上
if ([self pointInside:point withEvent:event] == NO) return nil;
// 3.从后往前遍历子控件
int count = (int)self.subviews.count;
for (int i = count - 1; i >= 0 ; i--) {
// 取出显示在最前面的子控件
UIView *childView = self.subviews[i];
// 转换成子控件坐标系上点
CGPoint childP = [self convertPoint:point toView:childView];
UIView *fitView = [childView hitTest:childP withEvent:event];
if (fitView) {
return fitView;
}
}
// 表示没有比自己更合适的view
return self;
}
事件传递的完整过程
1> 先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件。
2> 调用最合适控件的touches….方法
3> 如果调用了[super touches….];就会将事件顺着响应者链条往上传递,传递给上一个响应者
4> 接着就会调用上一个响应者的touches….方法
如何判断上一个响应者
1> 如果当前这个view是控制器的view,那么控制器就是上一个响应者
2> 如果当前这个view不是控制器的view,那么父控件就是上一个响应者
响应者链的事件传递过程
- 如果view的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图
- 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
- 如果window对象也不处理,则其将事件或消息传递给UIApplication对象
- 如果UIApplication也不能处理该事件或消息,则将其丢弃
响应者链条示意图
- 响应者链条:是由多个响应者对象连接起来的链条
- 作用:能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象处理。
- 响应者对象:能处理事件的对象
监听触摸事件的做法
- 如果想监听一个view上面的触摸事件,之前的做法是 自定义一个view
- 实现view的touches方法,在方法内部实现具体处理代码
- 通过touches方法监听view触摸事件,有很明显的几个缺点
- 1.必须得自定义view
- 由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件
- 不容易区分用户的具体手势行为
UIGestureRecognizer
- 为了完成手势识别,借助于手势识别器----UIGestureRecognizer
- 利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势
UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势
UITapGestureRecognizer(敲击)
UIPinchGestureRecognizer(捏合,用于缩放)
UIPanGestureRecognizer(拖拽)
UISwipeGestureRecognizer(轻扫)
UIRotationGestureRecognizer(旋转)
UILongPressGestureRecognizer(长按) Demo:https://github.com/SYLing/Gesture.git
iOS-控件响应用户控制事件之事件处理的更多相关文章
- 使用Devexpress中的CharControl控件,需要控制AxisY轴的显示范围,需要使用该控件的BoundDataChanged事件
一.控制ChartControl的Y轴范围 使用Devexpress中的CharControl控件,需要控制AxisY轴的显示范围,需要使用该控件的BoundDataChanged事件,具体代码如下: ...
- iOS控件之UIResponder类
iOS控件之UIResponder类 在iOS中UIResponder类是专门用来响应用户的操作处理各种事件的,我们知道UIApplication.UIView.UIViewController这几个 ...
- 如何设计一个 iOS 控件?(iOS 控件完全解析) (转)
前言 一个控件从外在特征来说,主要是封装这几点: 交互方式 显示样式 数据使用 对外在特征的封装,能让我们在多种环境下达到 PM 对产品的要求,并且提到代码复用率,使维护工作保持在一个相对较小的范围内 ...
- 如何设计一个 iOS 控件?(iOS 控件完全解析)
前言 一个控件从外在特征来说,主要是封装这几点: 交互方式 显示样式 数据使用 对外在特征的封装,能让我们在多种环境下达到 PM 对产品的要求,并且提到代码复用率,使维护工作保持在一个相对较小的范围内 ...
- 设计一个 iOS 控件
转载自:http://blog.csdn.net/zhangao0086/article/details/45622875 代码的等级:可编译.可运行.可测试.可读.可维护.可复用 前言 一个控件从外 ...
- UIControl IOS控件编程 及UITextField的讲解
第一部分 UIKit提供了一组控件:UISwitch开关.UIButton按钮.UISegmentedControl分段控件.UISlider滑块.UITextField文本字段控件.UIPageCo ...
- Asp.Net Form表单控件的回车默认事件
当form表单文本框控件在收到回车事件时,默认会触发表单内第一个可提交按钮的事件,但业务中可能要求有其它控件进行提交,而不是这个默认的 这时需要脚本控件事件冒泡传递取消回事事件. $(document ...
- IOS控件大全及控件大小
一 视图UIView和UIWindow iphone视图的规则是:一个窗口,多个视图.UIWindow相当于电视机,UIViews相当于演员. 1.显示数据的视图 下面几个类可在屏幕上显示信息: UI ...
- Windows控件的属性与事件
Treeview控件重要属性和事件 属性 说明 Nodes Treeview控件中所有树节点 SelectdNode 当前Treeview控件中选定的树节点,如果当前没有选定树节点,返回值为null ...
随机推荐
- asp.net mvc 中使用单例
有这样一个service,需要运行的asp.net站点上,但要保证这个实例是唯一的.单例用来启用聊天机器人,保证唯一,以免启动多个,造成客户端发送消息的时候,会造成每个机器人都发送消息,app收到多条 ...
- Java中有多少种设计模式?请简单画一下三种常见设计模式的类图?
转载:http://blog.csdn.net/longyulu/article/details/9159589 一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽 ...
- 一步一步学Silverlight 2系列(3):界面布局
述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
- frameset使用总结
frameset使用总结 2009-06-15 00:59 213人阅读 评论(0) 收藏 举报 框架bordermicrosoftinternethtml文档 FRAMESET 元素是 FRAME ...
- 【Idea】Debug模式
Idea则是把手标放到你想显示结果的代码上,按Ctrl+F1就显示结果. 如果你想跳到下一个断点直接按F9
- redhat输入用户名密码后又跳回到登录
一.如果忘记密码,可以进入single模式修改密码: 1.进入linux启动界面之后按e进入如下界面 2.按选择kernel /vmlinuz-2.4.20-8 ro root=LABEL=/ 项,按 ...
- codeforces 689D D. Friends and Subsequences(RMQ+二分)
题目链接: D. Friends and Subsequences time limit per test 2 seconds memory limit per test 512 megabytes ...
- Watir: 很久以前,对Watir开始学习时候做的笔记
1). buttons Xpath 1)Button properties browser.button(:xpath,"//input[@id='b2']/").name bro ...
- linuxmint安装卡在探测文件系统,解决方法。
今天安装linuxmint17.3,一直卡在探测文件... 解决方法如下: 执行安装程序前,打开终端执行如下命令即可. sudo umount -l /isodevic
- sqlsugar的sum的用法
通过论坛的检索 查到三篇文章是关于sum的 http://www.codeisbug.com/Ask/9/4531 http://www.codeisbug.com/Ask/14/4128 文章1:2 ...