• iOS开发核心动画之事件处理


    一. 事件

    1. iOS中事件分为三种

    • 触摸

    • 加速计

    • 远程

    2. 什么是响应者对象?

        继承了UIResponds的对象我们称它为响应者对象

        UIApplication、UIViewController、UIView都继承自UIResponder

        因此它们都是响应者对象,都能够接收并处理事件

        继承UIResponder称响应者对象

    3. 事件调用方法

    1> 触摸事件

    ```obj

    1. -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
    2. -(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event;
    3. -(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;
    4. -(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event;

    ```

    2> 加速计事件调用

    1. -(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent*)event;
    2. -(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent*)event;
    3. -(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent*)event;

    3> 远程控制事件

    1. -(void)remoteControlReceivedWithEvent:(UIEvent*)event;

    4. 完整触摸过程

    1. 触摸开始:
    2. -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
    3. 触摸移动:
    4. -(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
    5. 触摸结束:
    6. -(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
    7. 触摸取消(可能会经历,如来电时会调用):
    8. -(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event

    5. UIView拖拽

    1> 自定义UIView,实现监听方法.

    2> 确定在TouchMove方法当中进行操作,因为用户手指在视图上移动的时候才需要移动视图。

    3> 获取当前手指的位置和上一个手指的位置.

    4> 当前视图的位置 = 上一次视图的位置 + 手指的偏移量

     

     

    关健代码实现:

    • 拿到UITouch就能获取当前点

    1. UITouch*touch =[touches anyObject];
    • 获取当前点

    1. CGPoint curP =[touch locationInView:self];
    • 获取上一个点    

    1. CGPoint preP =[touch previousLocationInView:self];
    • 获取手指x轴偏移量

    1. CGFloat offsetX = curP.x - preP.x;
    • 获取手指y轴偏移量

    1. CGFloat offsetY = curP.y - preP.y;
    • 移动当前view

    1. self.transform =CGAffineTransformTranslate(self.transform, offsetX, offsetY);

    二. 事件的产生和传递

    1. 事件的产生和传递

        当发生一个触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中.

        UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理.

        主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件

        触摸事件的传递是从父控件传递到子控件的.

        如果一个父控件不能接收事件,那么它里面的了子控件也不能够接收事件.

    2. 一个控件什么情况下不能够接收事件

        . 不接收用户交互时不能够处理事件

          userInteractionEnabled = NO

        . 当一个控件隐藏的时候不能够接收事件

          Hidden = YES的时候

        . 当一个控件为透明白时候也不能够接收事件

     

        注意:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的

    3. 如何寻找合适的View

    1> 先判断自己是否能够接收触摸事件,如果能再继续往下判断,

    2> 再判断触摸的当前点在不在自己的身上.

    3> 如果在自己身上,它会从后往前遍历子控件,遍历出每一个子控件后,重复前面的两个步骤.

    4> 如果没有符合条件的子控件,那么它自己就是最适合的View.

    4. hitTest方法与PointInside方法

    1> hitTest方法寻找合适的View,只要一个事件传递给控件时就会调用

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

    2> PointInside方法判断当前点是否在此控件上(执行hitTest方法底层会调用此方法)

    1. -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event{
    2.     return YES;
    3. }

    注:point必须得要跟当前View同一个坐标系.

     

    5. hitText方法底层实现原理

    1. //作用:寻找最适合的View
    2. //什么时候调用:当事件传递给当前View时就会调用这个方法
    3. -(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{
    4.  
    5.    //1.判断自己能否接收事件
    6.    if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <=0.01){
    7.        return nil;
    8.    }
    9.    //2.触摸点在不在自己身上
    10.    if([self pointInside:point withEvent:event]== NO){
    11.        return nil;
    12.    }
    13.    //3.从后往前遍历自己的子控件(重复前面的两个步骤)
    14.    
    15.    int count =(int)self.subviews.count;
    16.    //2,count i = 1 i = 0
    17.    for(int i = count -1; i >=0; i--){
    18.        
    19.        //取出子控件
    20.        UIView*childV = self.subviews[i];
    21.        //point必须得要跟childV相同的坐标系.
    22.        
    23.        //把point转换childV坐标系上面的点
    24.        CGPoint childP =[self convertPoint:point toView:childV];
    25.        UIView*fitView =[childV hitTest:childP withEvent:event];
    26.        if(fitView){
    27.            return fitView;
    28.        }
    29.    }
    30.    
    31.    //4.如果没有符合条件的子控件,那么就自己最适合处理
    32.    return self;
    33. }

    三. 事件的响应和事件传递的完整过程

    1. 事件响应

        用户点击屏幕后产生的一个触摸事件,经过一系列的传递过程后,会找到最合适的视图控件来处理这个事件,

        找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理

        那这些touches方法的默认做法是将事件顺着响应者链条向上传递,将事件交给上一个响应者进行处理

     

     

    什么是响应者链条?

        是由多个响应者对象连接起来的链条.

     

     

    什么是响应者对象?

        继承了UIResponder对象我们称之为响应者对象,也就是能处理事件的对象

    2. 事件传递的完整过程?

        在产生一个事件时,系统会将该事件加入到一个由UIApplication管理的事件队列中,

        UIApplication会从事件队列中取出最前面的事件,将它传递给先发送事件给应用程序的主窗口.

        主窗口会调用hitTest方法寻找最适合的视图控件,找到后就会调用视图控件的touches方法来做具体的事情.

        当调用touches方法,它的默认做法, 就会将事件顺着响应者链条往上传递,

        传递给上一个响应者,接着就会调用上一个响应者的touches方法

     

     

    如何去寻找上一个响应者?

        1.如果当前的View是控制器的View,那么控制器就是上一个响应者.

        2.如果当前的View不是控制器的View,那么它的父控件就是上一个响应者.

        3.在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理

        4.如果window对象也不处理,则其将事件或消息传递给UIApplication对象

        5.如果UIApplication也不能处理该事件或消息,则将其丢弃

  • 相关阅读:
    再战设计模式(九)之组合模式
    再战设计模式(八)之桥接模式
    再战设计模式(七)之代理模式
    nyoj 题目2 括号配对问题
    剑指offer 面试题38
    杭电 1005
    九度oj 题目1552:座位问题
    九度oj 题目1482:玛雅人的密码 清华大学机试
    九度oj 题目1496:数列区间
    九度oj 题目1495:关键点
  • 原文地址:https://www.cnblogs.com/Xfsrn/p/4997533.html
Copyright © 2020-2023  润新知