UI技术总结--UI事件传递&响应

栏目: IOS · 发布时间: 7年前

内容简介:在讲述UI事件传递之前,先要知道UIView 和 UILayer的区别是什么.简而言之事件的传递主要和两个方法有关接下来来看看这个流程图

在讲述UI事件传递之前,先要知道UIView 和 UILayer的区别是什么.简而言之

  • UIView为其提供内容,以及负责处理触摸等事件,参与响应链
  • CALayer负责显示内容contents UIView只负责事件传递和视图响应链,而显示部分的内容都是由CALayer来负责, 这提现了系统设计UIView和CALayer中所运用的一个设计原则,就是单一职责原则.

接下来看看这幅图

UI技术总结--UI事件传递&响应
  • 思考一下,当点击图中白圈那个位置的时候,事件是如何进行传递的呢.

事件的传递主要和两个方法有关

// 返回哪个视图响应这个事件,返回nil表示不处理该事件
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
// 判断某一个点击的位置是否在视图范围内
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
复制代码

接下来来看看这个流程图

UI技术总结--UI事件传递&响应

首先,先判断视图的用户交互是否打开、是否隐藏、透明度是否大于0.01,如果有一个不符合,那么该视图将不处理任何事件响应,也不会进行后续的操作了.如果这三个条件都满足了,就会调用当前视图的 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 方法来判断点击的点是否在当前视图范围内,如果不在的话也会返回nil再由它当前视图的父视图去遍历它的同级兄弟视图,调用对应的 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法.如果当前视图的 -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 返回YES,那么就会以倒叙的方式遍历当前视图的子视图,遍历的过程中会调用所有自视图的 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法,如果某个子视图返回了最终的事件响应视图的话,就会把对应的视图作为最终的响应视图返回给调用方,如果返回的是nil的话就会继续遍历当前视图的下一个子视图.如果全部遍历完了之后都没有对应的子视图去响应事件的话,由于当前点击位置在当前视图范围内,就会把当前的视图作为响应视图返回给调用方.

通过一个例子来更深入的理解一下

在下图这个正方形按钮中,只有白色圆型区域可以响应点击事件.

UI技术总结--UI事件传递&响应
自定义一个button,通过 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

方法来实现上诉功能.

#import "CustomButton.h"

@implementation CustomButton

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (!self.userInteractionEnabled ||
        [self isHidden] ||
        self.alpha <= 0.01) {
        return nil;
    }
    // 如果点击区域在白色圆形区域内,则返回self,否则不响应事件
    if ([self pointInside:point withEvent:event]) {
            return self;
    }
    else{
        return nil;
    }
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGFloat x1 = point.x;
    CGFloat y1 = point.y;
    
    CGFloat x2 = self.frame.size.width / 2;
    CGFloat y2 = self.frame.size.height / 2;
    // 这就是传说中的勾股定理
    double dis = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    if (dis <= self.frame.size.width / 2) {
        return YES;
    }
    else{
        return NO;
    }
}

@end

复制代码

好了,现在这个自定义的button就实现了上述的功能了. 回到最开始的问题,点击那个白色位置,事件是如何进行传递的呢.如下图:

UI技术总结--UI事件传递&响应

首先点击位置在C2、B2、和A区域内,那么这3个视图都是有可能响应事件的.如果C2是B2的子视图,B2是A的子视图的话,那么按照顺序应该先调用子视图的 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法,而如果他们三个视图是平级的话,按照同级视图倒叙遍历的方式,也是C2先响应(因为C2覆盖在B2和A上).所以顺序就是C2先执行 -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 方法如果返回nil,B2再执行,最后才是A.如果都没有处理这个事件,那么最后会传到UIApplication,如果仍然没有处理这个事件,那么最后就会忽略这个事件.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTTP Essentials

HTTP Essentials

Stephen A. Thomas、Stephen Thomas / Wiley / 2001-03-08 / USD 34.99

The first complete reference guide to the essential Web protocol As applications and services converge and Web technologies not only assume HTTP but require developers to manipulate it, it is be......一起来看看 《HTTP Essentials》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码