hittest方法

  • 就是用来寻找最合适的view
  • 当一个事件传递给一个控件,就会调用这个控件的hitTest方法
  • 点击了白色的view: 触摸事件 -> UIApplication -> UIWindow 调用 [UIWindow hitTest] -> 白色view [WhteView hitTest]

实验1:

定义 BaseView,在里面实现方法touchBegan,监听当前哪个类调用了该方法。

定义KeyWindow,在里面实现hitTest方法,监听哪个类调用了该方法,用来追踪判断哪个view是最合适的view

在控制器的界面上加5个颜色不同的view,每个view自定义view去实现,因此在不同的view上的手势就可以由不同的view拦截到。

1
2
3
4
5
6
7
//KeyWindow
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
UIView *view = [super hitTest:point withEvent:event];
NSLog(@"fittest->%@",view);
return view;
}

结果:

点击了白色1:

1
2
3
4
5
6
2017-10-11 16:48:52.882547+0800 主流App框架[16295:358790] BrownView--hitTest withEvent
2017-10-11 16:48:59.646610+0800 主流App框架[16295:358790] GreenView--hitTest withEvent
2017-10-11 16:48:59.647145+0800 主流App框架[16295:358790] fittest-><UIView: 0x7f8f23406510; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x60c000221840>>
2017-10-11 16:48:59.647575+0800 主流App框架[16295:358790] BrownView--hitTest withEvent
2017-10-11 16:48:59.647702+0800 主流App框架[16295:358790] GreenView--hitTest withEvent
2017-10-11 16:48:59.647880+0800 主流App框架[16295:358790] fittest-><UIView: 0x7f8f23406510; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x60c000221840>>

点击了蓝色3:

1
2
3
4
5
6
7
8
9
10
11
2017-10-11 16:49:56.331024+0800 主流App框架[16295:358790] BrownView--hitTest withEvent
2017-10-11 16:49:56.331335+0800 主流App框架[16295:358790] BView--hitTest withEvent
2017-10-11 16:49:56.331617+0800 主流App框架[16295:358790] BlueView--hitTest withEvent
2017-10-11 16:49:56.331968+0800 主流App框架[16295:358790] YellowView--hitTest withEvent
2017-10-11 16:49:56.333206+0800 主流App框架[16295:358790] fittest-><BlueView: 0x7f8f23406f10; frame = (19 21; 240 128); autoresize = RM+BM; layer = <CALayer: 0x60c0002218c0>>
2017-10-11 16:49:56.333633+0800 主流App框架[16295:358790] BrownView--hitTest withEvent
2017-10-11 16:49:56.333762+0800 主流App框架[16295:358790] BView--hitTest withEvent
2017-10-11 16:49:56.333893+0800 主流App框架[16295:358790] BlueView--hitTest withEvent
2017-10-11 16:49:56.334005+0800 主流App框架[16295:358790] YellowView--hitTest withEvent
2017-10-11 16:49:56.334185+0800 主流App框架[16295:358790] fittest-><BlueView: 0x7f8f23406f10; frame = (19 21; 240 128); autoresize = RM+BM; layer = <CALayer: 0x60c0002218c0>>
2017-10-11 16:49:56.334644+0800 主流App框架[16295:358790] BlueView

那么看出来hitTest方法的作用就是找出最合适的view,那么我们可以指定任何事情的最合适的view为特定的view

实验2:

在KeyWindow中hitTest方法中返回BlueView,那么点击任何色块的view那么都会交给BlueView去处理事件。

1
2
3
4
//KeyWindow
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
return self.subviews.firstObject.subviews.firstObject;
}

结果:

1
2
2017-10-11 22:48:46.102793+0800 主流App框架[21498:749663] GreenView
2017-10-11 22:48:46.668595+0800 主流App框架[21498:749663] GreenView

因为事件的响应者链条就是当用户操作屏幕会产生一个事件,该事件被系统加入到事件队列中去,UIApplication对象会将事件队列中最早加入进去的事件传递给window,然后window找到最合适的view去处理事件。因此任何事件都会先通过KeyWindow对象去判断并找到最合适的view

2个重要的方法

  • -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event: 用来判断触摸点是否在控件上

  • -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event: 用来判断控件是否接受事件以及找到最合适的view

模仿系统实现找出最合适的view

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
31
//KeyWindow
/**
模仿系统实现寻找最合适的view步骤
1、控件接收事件
2、触摸点在自己身上
3、从后往前遍历子控件,重复前面2个步骤
4、如果没有符合条件的子控件,那么就自己最合适
*/
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) {
return nil;
}
if (![self pointInside:point withEvent:event]) {
return nil;
}
for (NSUInteger index = self.subviews.count - 1; index >= 0; index--) {
CGPoint childViewPoint = [self convertPoint:point toView:self.subviews[index]];
UIView *fitestView = [self.subviews[index] hitTest:childViewPoint withEvent:event];
if (fitestView) {
return fitestView;
}
return nil;
}
return self;
}

给出 一个Demo地址: github.com/FantasticLB…

实验:

在控制器(ViewController)的view上先添加一个UIButton,再添加一个自定义的UIView(ShelterView),盖在button的上面。

需求:点击ShelterView上的点,如果点也在UIButton范围上则交给UIButton处理事件,如果不在UIButton上则交给ShelterView处理,如果点击屏幕上除了ShelterView之外的点则交给控制器的view处理。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"viewController->%s",__func__);
}
//ShelterView
#import "ShelterView.h"
@implementation ShelterView
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__func__);
}
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
NSLog(@"%s",__func__);
/**
需求:不管点击按钮还是view都交给button处理
思路:在view的hitTest方法中寻找最合适的view,那么返回nil告诉系统view不是最合适的view,那么系统则认为按钮是最合适的view
return nil;
*/
//需求,在view上点击,如果点击范围在button上则由button进行处理事件;否则交给view处理事件
UIView *button = nil;
for (UIView *subView in self.superview.subviews) {
//判断事件的点是否在按钮上
if ([subView isKindOfClass:[UIButton class]]) {
button =subView;
}
CGPoint btnPoint = [self convertPoint:point toView:button];
if ([button pointInside:btnPoint withEvent:event]) {
return button;
}else{
//此时代表事件触摸点不在button上,但是也不能写nil,写nil的话点击屏幕上的其他地方系统会寻找最合适的view,此时返回nil( return nil;),则代表view不是最合适的view,那么此时点击屏幕上除了按钮之外的区域,最合适的view就是控制器上面的view
return [super hitTest:point withEvent:event];
}
}
return nil;
}
@end要看完整Demo,地址为:github.com/FantasticLB…

hitTest和pointInside方法相关推荐

  1. [ios2] UIView的hitTest,pointInside方法详解【转】

    关于UIView的触摸响应事件中,这里有一个常常容易迷惑的方法hitTest:WithEvent.先来看官方的解释:This method traverses the view hierarchy b ...

  2. UIView的hitTest和pointInside方法

    官方描述 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; Returns a Boolean value indicati ...

  3. hitTest和pointInside如何响应用户点击事件

    hitTest和pointInside如何响应用户点击事件 处理机制 iOS事件处理,首先应该是找到能处理点击事件的视图,然后在找到的这个视图里处理这个点击事件. 处理原理如下: • 当用户点击屏幕时 ...

  4. TOCControl 的HitTest()方法

    public void HitTest ( int X, int Y, ref esriTOCControlItem ItemType, ref IBasicMap BasicMap, ref ILa ...

  5. ios事件-触摸事件2(手势 和 pointInSide()、hitTest()、touchesBegan()、touchesMoved()、touchesEnded()的关系)

    ios事件-触摸事件2(手势 和 pointInSide().hitTest().touchesBegan().touchesMoved().touchesEnded().touchesCancell ...

  6. [IOS]hitTest的作用与用法【转】

    hitTest的作用:当在一个view上添加一个屏蔽罩,但又不影响对下面view的操作,也就是可以透过屏蔽罩对下面的view进行操作,这个函数就很好用了. hitTest的用法:将下面的函数添加到UI ...

  7. iOS 的UIView 的hitTest的分析

    hitTest的用法: (1)当在一个view上添加一个屏蔽罩,但又不影响对下面view的操作,也就是可以透过屏蔽罩对下面的view进行操作,这个函数就很好用了. 将下面的函数添加到UIView的子类 ...

  8. hitTest:(CGPoint)point withEvent:(UIEvent *)event

    UIView的hitTest:方法和pointInside:方法的实现 2015-03-31       0 个评论    来源:zhangping871的专栏    收藏     我要投稿 ? 1 ...

  9. IOS 收起键盘的几种方法(转)

    在iOS应用开发中,有三类视图对象会打开虚拟键盘,进行输入操作,但如何关闭虚拟键盘,却没有提供自动化的方法.这个需要我们自己去实现.这三类视图对象分别是UITextField,UITextView和U ...

最新文章

  1. win10访问不了局域网计算机名,Win10正式版无法访问局域网电脑怎么办
  2. 中国移动物联网客户规模突破2600家 联网接入终端达2300万台
  3. 利用快排查询无序数组第k位大的数
  4. 深拷贝、浅拷贝以及引用传递和按值传递的区别与联系
  5. 理解关联容器“map”的关键点
  6. 【英语学习】【WOTD】muse 释义/词源/示例
  7. PHP如何在微信中聊天_迷你微信私有聊天系统PHP源码支持PC、移动APP
  8. pos5890打印机测试软件,pos5890热敏票据打印机驱动
  9. PPP项目群管理模式的实践探索——以浙江交工富阳PPP项目群为例
  10. Grounded video description
  11. 阿涛读书之——《坏血》
  12. Adobe Illustrator【印前角线X2.0】脚本源码
  13. Android中的三级缓存机制
  14. ClickHouse 之 FORMAT 应用
  15. 过零检测法MATLAB仿真,过零检测 - MATLAB Simulink - MathWorks 中国
  16. 《麦肯锡精英的谈判策略》 -豆瓣评分8.2
  17. 23.从0学ARM-网卡DM9000及uboot协议栈详解
  18. 哪个品牌台灯护眼效果好?2023热门护眼灯品牌推荐
  19. OC语言1-前期准备
  20. linux系统和windows系统硬盘组raid方法

热门文章

  1. 发现一个浏览器很奇怪的问题
  2. 无序数组及其子序列的相关问题研究
  3. 机器学习:协方差矩阵
  4. 【转载】解决Apache2+PHP上传文件大小限制的问题
  5. HTTP头信息中的参数Etag
  6. 使用DataGrid动态绑定DropDownList
  7. 常用Maven收集以及Maven技巧
  8. 二维码Data Matrix的解码实现(zxing-cpp)
  9. 【C++】C++命名空间重定向
  10. travis-ci如何配置android