iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景.
2019独角兽企业重金招聘Python工程师标准>>>
主要是记录下iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景.
一、处理机制
界面响应消息机制分两块,(1)首先在视图的层次结构里找到能响应消息的那个视图。(2)然后在找到的视图里处理消息。
【关键】(1)的过程是从父View到子View查找,而(2)是从找到的那个子View往父View回溯(不一定会往回传递消息)。
1.1、寻找响应消息视图的过程可以借用M了个J的一张图来说明。
处理原理如下:
• 当用户点击屏幕时,会产生一个触摸事件,系统会将该事件加入到一个由UIApplication管理的事件队列中
• UIApplication会从事件队列中取出最前面的事件进行分发以便处理,通常,先发送事件给应用程序的主窗口(UIWindow)
• 主窗口会调用hitTest:withEvent:方法在视图(UIView)层次结构中找到一个最合适的UIView来处理触摸事件
(hitTest:withEvent:其实是UIView的一个方法,UIWindow继承自UIView,因此主窗口UIWindow也是属于视图的一种)
• hitTest:withEvent:方法大致处理流程是这样的:
首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内:
▶ 若pointInside:withEvent:方法返回NO,说明触摸点不在当前视图内,则当前视图的hitTest:withEvent:返回nil
▶ 若pointInside:withEvent:方法返回YES,说明触摸点在当前视图内,则遍历当前视图的所有子视图(subviews),调用子视图的hitTest:withEvent:方法重复前面的步骤,子视图的遍历顺序是从top到bottom,即从subviews数组的末尾向前遍历,直到有子视图的hitTest:withEvent:方法返回非空对象或者全部子视图遍历完毕:
▷ 若第一次有子视图的hitTest:withEvent:方法返回非空对象,则当前视图的hitTest:withEvent:方法就返回此对象,处理结束
▷ 若所有子视图的hitTest:withEvent:方法都返回nil,则当前视图的hitTest:withEvent:方法返回当前视图自身(self)
• 最终,这个触摸事件交给主窗口的hitTest:withEvent:方法返回的视图对象去处理。
拿到这个UIView后,就调用该UIView的touches系列方法。
1.2、消息处理过程,在找到的那个视图里处理,处理完后根据需要,利用响应链nextResponder可将消息往下一个响应者传递。
UIAppliactionDelegate <- UIWindow <- UIViewController <- UIView <- UIView
【关键】:要理解的有三点:1、iOS判断哪个界面能接受消息是从View层级结构的父View向子View传递,即树状结构的根节点向叶子节点递归传递。2、hitTest和pointInside成对,且hitTest会调用pointInside。3、iOS的消息处理是,当消息被人处理后默认不再向父层传递。
二、应用实例
【需求】是:界面如下,
Window
-ViewA
-ButtonA
-ViewB
-ButtonB
层次结构:ViewB完全盖住了ButtonA,ButtonB在ViewB上,现在需要实现1)ButtonA和ButtonB都能响应消息 2)ViewA也能收到ViewB所收到的touches消息 3)不让ViewB(ButtonB)收到消息。
(首先解析下,默认情况下,点击了ButtonB的区域,iOS消息处理过程。
-ViewA
-ButtonA
-ViewB
-ButtonB
当点击ButtonB区域后,处理过程:从ViewA开始依次调用hitTest
pointInside的值依次为:
ViewA:NO;
ViewB:YES;
ButtonB:YES;
ButtonB的subViews:NO;
所以ButtonB的subViews的hitTest都返回nil,于是返回的处理对象是ButtonB自己。接下去开始处理touches系列方法,这里是调用ButtonB绑定的方法。处理完后消息就停止,整个过程结束。)
【分析】:
实现的方式多种,这里将两个需求拆解开来实现,因为实现2就可以满足1。
2.1、需求1的实现,ViewB盖住了ButtonA,所以默认情况下ButtonA收不到消息,但是在消息机制里寻找消息响应是从父View开始,所以我们可以在ViewA的hitTest方法里做判断,若touch point是在ButtonA上,则将ButtonA作为消息处理对象返回。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#pragma mark - hitTest
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// 当touch point是在_btn上,则hitTest返回_btn
CGPoint btnPointInA = [_btn convertPoint:point fromView: self ];
if ([_btn pointInside:btnPointInA withEvent:event]) {
return _btn;
}
// 否则,返回默认处理
return [ super hitTest:point withEvent:event];
}
|
这样,当触碰点是在ButtonA上时,则touch消息就被拦截在ViewA上,ViewB就收不到了。然后ButtonA就收到touch消息,会触发onClick方法。
2.2、需求2的实现,上面说到响应链,ViewB只要override掉touches系列的方法,然后在自己处理完后,将消息传递给下一个响应者(即父View即ViewA)。
代码如下:在ViewB代码里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#pragma mark - touches
- ( void )touchesBegan:( NSSet *)touches withEvent:(UIEvent *)event
{
NSLog (@ "B - touchesBeagan.." );
// 把事件传递下去给父View或包含他的ViewController
[ self .nextResponder touchesBegan:touches withEvent:event];
}
- ( void )touchesCancelled:( NSSet *)touches withEvent:(UIEvent *)event
{
NSLog (@ "B - touchesCancelled.." );
// 把事件传递下去给父View或包含他的ViewController
[ self .nextResponder touchesBegan:touches withEvent:event];
}
- ( void )touchesEnded:( NSSet *)touches withEvent:(UIEvent *)event
{
NSLog (@ "B - touchesEnded.." );
// 把事件传递下去给父View或包含他的ViewController
[ self .nextResponder touchesBegan:touches withEvent:event];
}
- ( void )touchesMoved:( NSSet *)touches withEvent:(UIEvent *)event
{
NSLog (@ "B - touchesMoved.." );
// 把事件传递下去给父View或包含他的ViewController
[ self .nextResponder touchesBegan:touches withEvent:event];
}
|
然后,在ViewA上就可以接收到touches消息,在ViewA上写:
+ View Code
这样就实现了向父View透传消息。
2.3 、不让ViewB收到消息,可以设置ViewB.UserInteractionEnable=NO;除了这样还可以override掉ViewB的ponitInside,原理参考上面。
在ViewB上写:
+ View Code
转载于:https://my.oschina.net/u/2483781/blog/547853
iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景.相关推荐
- Android 触摸事件处理机制
Android 触摸事件的处理主要涉及到几个方法: onInterceptTouchEvent(), dipatchTouchEvent(), onTouchEvent(), onTouch() ...
- Android开发之触摸事件处理机制详解
android触碰消息传递机制 用户的每次触碰(onClick,onLongClick,onScroll,etc.)都是由一个ACTION_DOWN+n个ACTION_MOVE+1个ACTION ...
- Cocos2d-x Touch事件处理机制(better)
from http://www.2cto.com/kf/201308/236359.html 注:下面这位同学对于cocos2d-x 2.x中的触摸机制分析简直可以说是清晰到家了. 重要补充: 下面这 ...
- Action与ActionListener的事件处理机制及实例分析
xjtuer最好不要抄,五次作业都是去年优秀作业,被老师逮住全给0分就得不偿失了,放在这里是给大家一个思路不用再去查找很多资料,了解之后再自己总结写一写 事件处理机制的分析 swing的事件处理机制其 ...
- java pc的录制与回放,用Java事件处理机制实现录制回放功能
下载本文示例代码 目前在一些java应用程序的GUI测试工具,可以提供捕获用户操作的能力并在代码被修改之后能够自动回放用户的操作.文章将分析Java的事件处理模型及其原理,介绍了基于事件源识别的捕获/ ...
- iOS UITouch 触摸事件处理
1. UITouch 的主要方法: C代码 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; - (void)to ...
- iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控
-- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...
- Android平台的事件处理机制和手指滑动例子
Android平台的事件处理机制有两种 基于回调机制的事件处理:Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通过重写View中的这些回调方法来实现需要的响应事件. 基于 ...
- Cocos2d-JS事件处理机制
在很多图形用户技术中,事件处理机制一般都有三个重要的角色:事件.事件源和事件处理者.事件源是事件发生的场所,通常就是各个视图或控件,事件处理者是接收事件并对其进行处理的一段程序. 事件处理机制中三个角 ...
最新文章
- Java设计模式(建造者模式-适配器模式-桥接模式)
- 学业水平考试b能上985吗_211 和985 的大学是不是要求学业水平考试全部是A
- Spring Cloud:多网卡问题
- 《ASP.NET Core项目开发实战入门》送书活动结果公布
- 带你一文看懂 Blockchain + NoSQL数据库
- 上岸 | 震惊!211高校硕士毕业后,我在非洲当酋长!
- SQL Server中删除重复数据的几个方法
- 循环 计算数值的整数次幂
- ios java aes_PHP7 AES加密解密函数_兼容ios/andriod/java对等加解密
- 利用Drawable绘制圆角图片和圆形图片
- 谷歌邮箱lmap服务器填什么_GMAIL邮箱IMAP设置
- Last packet sent to the server was 2 ms ago 解决办法
- 三点法求三维坐标精度误差评估实验
- 大数据学习之一——Hadoop单机部署
- Android开发音乐播放器
- 分布式共识算法随笔 —— 从 Quorum 到 Paxos
- Java中BIO,NIO,AIO
- [Linux] USB-Storage驱动 源码阅读笔记(一)
- 《勇士传说》横版卷轴动作类游戏笔记-3.场景绘制和叠层设置
- oracle9i连接12,12c使用DBLINK连接9i报ORA-03134