zoukankan      html  css  js  c++  java
  • 超出父视图无法点击问题hitTest

     

    iOS之事件的传递和响应机制-原理篇:   http://www.jianshu.com/p/2e074db792ba

     

     

    //重写父视图的hitTest: withEvent:方法 ,从而使子视图完成相应的响应

     

    #import <UIKit/UIKit.h>

     

    @interface XSView : UIView

     

    @property(nonatomic,strong)UIButton *btn;

     

    @end

     

     

     

     

    @implementation XSView

     

     

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

        

        UIView *result = [super hitTest:point withEvent:event];

        

       //将 btn 上的点转换到 self 上

        CGPoint buttonPoint = [self.btn convertPoint:point fromView:self];

     

        // 判断点在不在按钮上

        if ([self.btn pointInside:buttonPoint withEvent:event]) {

            

            return self.btn;

        }

        

        return result;

        

    }

     

    //如果在按钮的触碰范围内,则按钮相应,否则的话 则View相应

     

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    处理原理如下:

    ? 当用户点击屏幕时,会产生一个触摸事件,系统会将该事件加入到一个由UIApplication管理的事件队列中

    ? UIApplication会从事件队列中取出最前面的事件进行分发以便处理,通常,先发送事件给应用程序的主窗口(UIWindow)

    ? 主窗口会调用hitTest:withEvent:方法在视图(UIView)层次结构中找到一个最合适的UIView来处理触摸事件

    (hitTest:withEvent:其实是UIView的一个方法,UIWindow继承自UIView,因此主窗口UIWindow也是属于视图的一种)

    ? hitTest:withEvent:方法大致处理流程是这样的:

    首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内:

    ? 若pointInside:withEvent:方法返回NO,说明触摸点不在当前视图内,则当前视图的hitTest:withEvent:返回nil

    ? 若pointInside:withEvent:方法返回YES,说明触摸点当前视图内,则遍历当前视图的所有子视图(subviews),调用子视图的hitTest:withEvent:方法重复前面的步骤,子视图的遍历顺序是从top到bottom,即从subviews数组的末尾向前遍历,直到有子视图的hitTest:withEvent:方法返回非空对象或者全部子视图遍历完毕:

    ? 若第一次有子视图的hitTest:withEvent:方法返回非空对象,则当前视图的hitTest:withEvent:方法就返回此对象,处理结束

    ? 若所有子视图的hitTest:withEvent:方法都返回nil,则当前视图的hitTest:withEvent:方法返回当前视图自身(self)

    ? 最终,这个触摸事件交给主窗口的hitTest:withEvent:方法返回的视图对象去处理。

    拿到这个UIView后,就调用该UIView的touches系列方法。

    1.2、消息处理过程,在找到的那个视图里处理,处理完后根据需要,利用响应链nextResponder可将消息往下一个响应者传递。

    UIAppliactionDelegate <- UIWindow <- UIViewController <- UIView <- UIView

    【关键】:要理解的有三点:1、iOS判断哪个界面能接受消息是从View层级结构的父View向子View传递,即树状结构的根节点向叶子节点递归传递。2、hitTest和pointInside成对,且hitTest会调用pointInside。3、iOS的消息处理是,当消息被人处理后默认不再向父层传递

     

     

     //区别:

     

    toView就是从左往右开始读代码,也是从左往右理解意思

    fromView就是从右往左开始读代码,也是从右往左理解意思

    A(CGPoint)convertPoint:B(CGPoint)point toView:C(nullable UIView *)view;

    - A(CGPoint)convertPoint:B(CGPoint)point fromView:C(nullable UIView *)view;

    第一句代表

    A区域里面有个坐标B,需要把相对于A的坐标B转换成相对于C的坐标

     

    第二句代表

    从C区域里面转换坐标B,需要把相对于C的坐标转换成相对于A的坐标

     

     

     

     

     

     

  • 相关阅读:
    sql2slack alash3al 开源的又个轻量级工具
    pgspider fetchq 扩展docker镜像
    godns 集成coredns 的demo
    godns 简单dnsmasq 的dns 替换方案
    aviary.sh 一个基于bash的分布式配置管理工具
    使用coredns 的template plugin实现一个xip 服务
    nginx 代理 coredns dns 服务
    基于nginx proxy dns server
    几个不错的geodns server
    spring boot rest api 最好添加servlet.context-path
  • 原文地址:https://www.cnblogs.com/daxueshan/p/6383493.html
Copyright © 2011-2022 走看看