为了账号安全,请及时绑定邮箱和手机立即绑定

iOS 响应链

标签:
iOS

应用与用户的交互是一个应用的灵魂。

点击、摇动、滑动、旋转等会被系统封装成UIEvent,放到事件队列里等待UIApplication去取,然后寻找响应者,找到对应的方法并执行的过程就是响应。

这里寻找最佳响应者依靠两个方法:
方法一返回最佳响应者
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
方法二判断点有没有在返回的视图范围内
- -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

调用顺序是
调用方法一,在遍历找到一个视图就通过方法二判断是否符合条件,符合就返回该视图

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{
	 // 1.判断当前控件能否接收事件
   if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
    // 2. 判断点在不在当前视图内
   if ([self pointInside:point withEvent:event] == NO) return nil;
     // 3.从后往前遍历自己的子视图
   NSInteger count = self.subviews.count;
   for (NSInteger i = count - 1; i >= 0; i--) {
       UIView *childView = self.subviews[I];
       // 把当前控件上的坐标系转换成子控件上的坐标系
    CGPoint childP = [self convertPoint:point toView:childView];
      UIView *fitView = [childView hitTest:childP withEvent:event];
       if (fitView) { // 寻找到最合适的view
           return fitView;
       }
   }
   // 循环结束,表示没有比自己更合适的view 就返回自身
   return self;
}

注意遍历子视图是从最后添加的子视图往下遍历

图片描述

如上图视图A和视图B
A、B都能响应事件。切在同一父视图上的前提下,点击中间的重叠区域,响应者是?
这就看是A先添加还是B先添加了,A先B后,根据响应链肯定是B响应
,反之则A响应

增加按钮响应范围的方法

分类里重写

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGRect bounds = self.bounds;
    bounds = CGRectInset(bounds, -10, -10);
    return CGRectContainsPoint(bounds, point);
}
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
32
获赞与收藏
322

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消