【原】ios的hitTest方法以及不规则区域内触摸事件处理方法

简介:

概述

在正常的使用场景中,我们处理了比较多的矩形区域内触摸事件,比如UIButton、UIControl。一般来说,这些控件的图形以及触摸区域都是矩形或者圆角矩形的。但是在一些特殊应用场景中我们有时不得不面对这样一种比较严苛的需求,比如要求程序只对某个圆形、五角形等非常规区域的点击事件进行处理,这就需要花点功夫了。本文以圆形为例子来介绍此类场景的处理方法。

先看下面一张图(附图1),我们的目标是实现如下自定义tabbar。中间带突起圆形的自定义tabbar曾一度流行,今天我们来粗糙地实现一下。

在附图一中,红色代表tabbar,上面有三个蓝色按钮。在三个按钮中我们重点解决按钮A,因为它有一半的区域突在tabbar的有效区域外。

对于按钮A,我们有以下两个问题需要解决:

1、如何准确过滤掉A外接矩形里非蓝色区域的点击事件?

2、如何让A的上半部分也能响应触摸事件?

 

其实两个问题的解决方法是基本一致的。在iOS中所有控件都是以矩形的方式存在的,在图2中尽管蓝色部分看起来是圆形,但当点击外接矩形内的非圆形区域时也会默认触发点击事件。因此,我们需要用一些手段把触摸事件“拦截”下来。想要“拦截”事件,就必须了解iOS的事件分发机制,也就是当你点击设备屏幕后,iOS是如何决定由那个view去最终响应你的触摸!下面插播一小段关于iOS事件分发的介绍:

==================================

当你手指触摸屏幕后会发生以下事情:触摸事件被封装成一个UIEvent事件,去当前iOS操作系统的active app队列中取当前活跃的APP,把event传给它--->event传给UIApplication--->传给UIWindow的root view controller(rootVC)--->调用rootVC.view的所有subviews的hitTest:event:方法。哪个view的hitTest:event方法返回非nil值,则触摸事件就交给该view处理。关于事件分发的详细机制及举例可以参考技术哥大神的文章

==================================

分析

让我们重新回到探讨的问题上。通过以上简介我们可以知道,想“拦截”触摸事件,则应该在tabbar的hitTest:event方法中做处理(坐标判断等)。以下是具体的demo源码:

 

  panelView.h
  panelView.m(控件初始化,不展开)

 

在hitTest方法中最重要的是判断按钮A所在的区域,其实仅仅用到两点的距离公式来圈出蓝色部分所在的圆形,判断方法如下:

1
2
3
4
5
6
- ( BOOL )touchPointInsideCircle:(CGPoint)center radius:(CGFloat)radius targetPoint:(CGPoint)point
{
     CGFloat dist = sqrtf((point.x - center.x) * (point.x - center.x) +
                          (point.y - center.y) * (point.y - center.y));
     return  (dist <= radius);
}

 

而判断点是否在按钮B/C内就更简单了,系统提供了封装好的api:

1
bool  CGRectContainsPoint(CGRect rect, CGPoint point)

 

最终,关于事件“拦截”的判断如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
     UIView *hitView =  nil ;
     //NSLog(@"point:%@", NSStringFromCGPoint(point));
     UIButton *roundBtn = (UIButton *)[ self  viewWithTag:10086];
     UIButton *leftBtn = (UIButton *)[ self  viewWithTag:10087];
     UIButton *rightBtn = (UIButton *)[ self  viewWithTag:10088];
     BOOL  pointInRound = [ self  touchPointInsideCircle:roundBtn.center radius:30 targetPoint:point];
     if  (pointInRound) {
         hitView = roundBtn;
    else  if (CGRectContainsPoint(leftBtn.frame, point)) {
         hitView  = leftBtn;
     else  if (CGRectContainsPoint(rightBtn.frame, point)) {
         hitView = rightBtn;
     else  {
         hitView =  self ;
     }
     return  hitView;
}

  

此外,在hitTest中还可以玩其他花样,比如将本该由按钮A响应的时间强制性转发给其他按钮,这只需在hitTest的返回值中修改一下即可!

本文所用demo完整源码点这里test.zip下载。

      

                   图1                   图2

 

本文转自编程小翁博客园博客,原文链接:http://www.cnblogs.com/wengzilin/p/4249847.html,如需转载请自行联系原作者

相关文章
|
19天前
|
移动开发 前端开发 数据安全/隐私保护
iOS发布证书.p12文件无密码解决办法及导出带密码的新.p12文件方法
iOS发布证书.p12文件无密码解决办法及导出带密码的新.p12文件方法
24 0
|
3月前
|
存储 监控 iOS开发
iOS应用崩溃了,如何通过崩溃手机连接电脑查找日志方法
在iOS应用开发过程中,调试日志和奔溃日志是开发者必不可少的工具。当iOS手机崩溃时,我们可以连接电脑并使用Xcode Console等工具来查看日志。然而,这种方式可能不够方便,并且处理奔溃日志也相当繁琐。克魔助手的出现为开发者带来了极大的便利,本文将详细介绍其功能和使用方法。 克魔助手会提供两种日志,一种是实时的,一种的是崩溃的。(由于崩溃日志的环境很麻烦,目前只展示实时日志操作步骤)
|
3月前
|
存储 iOS开发 开发者
使用克魔助手进行iOS数据抓包和HTTP抓包的方法详解
使用克魔助手进行iOS数据抓包和HTTP抓包的方法详解
42 0
|
3月前
|
安全 编译器 开发工具
​iOS安全加固方法及实现
​iOS安全加固方法及实现
30 0
​iOS安全加固方法及实现
|
4月前
|
iOS开发 开发者
📝 App备案与iOS云管理式证书 ,公钥及证书SHA-1指纹的获取方法
在iOS应用程序开发过程中,进行App备案并获取公钥及证书SHA-1指纹是至关重要的步骤。本文将介绍如何通过appuploader工具获取iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹,帮助开发者更好地理解和应用该过程。
|
3月前
|
小程序 前端开发 Android开发
解决小程序中textarea ios端样式不兼容的两种方法
解决小程序中textarea ios端样式不兼容的两种方法
|
19天前
|
Android开发 iOS开发 开发者
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
66 0
|
19天前
|
安全 编译器 开发工具
​iOS安全加固方法及实现
​iOS安全加固方法及实现
17 0
|
5月前
|
Android开发 iOS开发 开发者
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
,在appuploder直接复制IOS信息;如果还没有创建证书,请上传正确的P12苹果证书后,系统会自动解析出对应的签名和公钥信息; ——APP备案的原理是基于原有的工信部域名备案系统,如果已经有了域名备案,无需新增备案主体;只需要在之前的域名备案系统里面,新增APP信息,收集的APP信息主要包括APP包名和签名及公钥这3项;——APP备案是属于行政常规主体信息预存,和域名一样,自行决定是否备案。目前国内安卓应用商店是全面要求APP备案的,如果没有APP备案是不能通过审核发布到各大应用商店。——如看了教程,还不清楚怎么获取APP包名、安卓签名、苹果sha1签名、公钥等信息,请联系我们在线客服,
|
6月前
|
网络安全 开发工具 数据安全/隐私保护
如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总
如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总