举例讲解iOS应用开发中hitTest触摸事件的编写方法

 更新时间:2016年04月11日 09:06:52   作者:Quains  
这篇文章主要介绍了举例讲解iOS应用开发中hitTest触摸事件的编写方法,重点讲解了两个view之间的事件传递,需要的朋友可以参考下

 hitTest:withEvet  调用过程

比如如果是当前的View A, 还有一个viewB

如果不重写 hitTest 方法,那么 系统默认是先调用viewA的hitest 方法,然后再调用viewB的htest方法。

系统的调用过程,跟下面的重写hitest的方法是一模一样的。

复制代码 代码如下:

-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

    if ([self pointInside:point withEvent:event]) { 
    } 
    else { 
        return nil; 
    } 
    for (UIView *subView in self.subviews) { 
        if ([subView hitTest:point withEvent:event]!=nil) { 
            return subView; 
        } 
    } 
     
    return self; 


在说明一次,如果不重写hitest方法,那么每一个UIVIeew的默认hitest的方法都是上面这个处理流程。

那也没啥好说的。

但是对于一些特殊的处理过程,就不行了

所以之所以重写hitTest方法,通常都是为了穿透上层 的 UIview,让touch事件可以达到下面的uiview,

比如 view A  和 VIew B,

View b完全挡住了view A,但是我想让点击viewB的时候,view A可以响应点击的事件。就可以采用下面的方法:

复制代码 代码如下:

-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

    if ([self pointInside:point withEvent:event]) { 
        NSLog(@"in view A"); 
        return self; 
    } 
    else { 
        return nil; 
    } 
 

深入
我们来更深入一下,现在有个实例需求界面如下,

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。

需求1的实现,ViewB盖住了ButtonA,所以默认情况下ButtonA收不到消息,但是在消息机制里寻找消息响应是从父View开始,所以我们可以在ViewA的hitTest方法里做判断,若touch point是在ButtonA上,则将ButtonA作为消息处理对象返回。

代码如下:

复制代码 代码如下:

#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的实现,上面说到响应链,ViewB只要override掉touches系列的方法,然后在自己处理完后,将消息传递给下一个响应者(即父View即ViewA)。

代码如下:在ViewB代码里

复制代码 代码如下:

#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上写:
复制代码 代码如下:

#pragma mark - touches
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"A - touchesBeagan..");
}
 
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"A - touchesCancelled..");
}
 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"A - touchesEnded..");
}
 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"A - touchesMoved..");
    
}

这样就实现了向父View透传消息。

不让ViewB收到消息,可以设置ViewB.UserInteractionEnable=NO;除了这样还可以override掉ViewB的ponitInside,原理参考上面。

在ViewB上写:

复制代码 代码如下:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    // 本View不响应用户事件
    return NO;
 
}

相关文章

  • iOS实现UITableView数据为空时的提示页面

    iOS实现UITableView数据为空时的提示页面

    最近工作中遇到一个需求,当UITableView数据为空的时候,给出一个简单的提示页面,通过从网上查找解决的方法,发现了两种实现的方法,现在分享给大家,有需要的朋友们可以参考借鉴,下面感兴趣的朋友们来一起学习学习吧。
    2016-11-11
  • iOS 中 使用UITextField格式化银行卡号码的解决方案

    iOS 中 使用UITextField格式化银行卡号码的解决方案

    今天小编给大家分享ios中使用UITextField格式化银行卡号码的实现思路详解,非常不错,具有参考借鉴价值,需要的朋友参考下
    2016-12-12
  • 全面解析iOS中同步请求、异步请求、GET请求、POST请求

    全面解析iOS中同步请求、异步请求、GET请求、POST请求

    通过本文给大家全面解析了iOS中同步请求、异步请求、GET请求、POST请求,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-08-08
  • 谈谈制作iOS Ad-Hoc测试应用

    谈谈制作iOS Ad-Hoc测试应用

    这篇文章主要介绍了谈谈制作iOS Ad-Hoc测试应用,AD-HOC测试是指随机测试,这种测试的特点是无特定的测试用例,有兴趣的可以了解一下。
    2016-12-12
  • iOS开发之路--仿网易抽屉效果

    iOS开发之路--仿网易抽屉效果

    本文是IOS开发之路系列的第一篇,主要讲诉了如何仿网易新闻客户端实现抽屉效果,全部源代码都分享给大家,希望对大家有所帮助
    2014-08-08
  • iOS滑动全屏实现返回功能

    iOS滑动全屏实现返回功能

    这篇文章主要为大家详细介绍了iOS滑动全屏实现返回功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • iOS7 毛玻璃特效代码

    iOS7 毛玻璃特效代码

    这篇文章主要分享了iOS7 毛玻璃特效代码,非常的实用,做IOS开发的童鞋们不要错过了
    2014-10-10
  • 浅谈iOS 对于block的一点理解

    浅谈iOS 对于block的一点理解

    本篇文章主要介绍了iOS 对于block的一点理解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • IOS实现邮箱模糊匹配的功能

    IOS实现邮箱模糊匹配的功能

    在一些App的订单填写页,输入用户邮箱有个提示邮箱后缀的功能,很好用!还可以根据各个邮箱类型用户量来做一个优先级的匹配哦。这个功能该如何实现呢,下面来一起看看。
    2016-08-08
  • iOS实现选项卡效果的方法

    iOS实现选项卡效果的方法

    选项卡在我们日常开发的时候经常要用到,所以这篇文章给大家分享一种iOS实现的简单选项卡效果,很适合大家学习和使用,有需要的可以参考借鉴,下面来一起看看吧。
    2016-09-09

最新评论