zoukankan      html  css  js  c++  java
  • iOS-控件响应用户控制事件之事件处理

    事件处理

    响应者对象

    • 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。我们称之为“响应者对象”

    • UIApplication、UIViewController、UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件

    UIResponder内部提供了以下方法来处理事件

    • 这些类可以覆盖下列几个方法处理不同的触摸事件 ```objc //触摸事件
    • (void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event;
    • (void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event;
    • (void)touchesEnded:(NSSet )touches withEvent:(UIEvent )event;
    • (void)touchesCancelled:(NSSet )touches withEvent:(UIEvent )event;

    //加速计事件

    • (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
    • (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
    • (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;

    //远程控制事件

    • (void)remoteControlReceivedWithEvent:(UIEvent *)event; ```

    事件的参数

    UITouch

    UITouch的作用
    • 保存着跟手指相关的信息,比如触摸的位置、时间、阶段
    • 当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在的触摸位置
    • 当手指离开屏幕时,系统会销毁相应的UITouch对象
    UITouch的方法
    - (CGPoint)locationInView:(UIView *)view;
    
    • 返回值表示触摸在view上的位置
    • 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0))
    • 调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
    - (CGPoint)previousLocationInView:(UIView *)view;
    
    • 该方法记录了前一个触摸点的位置

    UIEvent

    • 每产生一个事件,就会产生一个UIEvent对象
    • UIEvent:称为事件对象,记录事件产生的时刻和类型

    常见属性

    事件类型
    @property(nonatomic,readonly) UIEventType     type;
    @property(nonatomic,readonly) UIEventSubtype  subtype;
    

    事件产生的时间

    @property(nonatomic,readonly) NSTimeInterval  timestamp;
    

    事件的产生和传递

      1. 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中。
    • 2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)
    • 3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步
    • 4.找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理
    touchesBegan…
    touchesMoved…
    touchedEnded…
    

    如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件(掌握)

    如何找到最合适的控件来处理事件?

    • 自己是否能接收触摸事件?
    • 触摸点是否在自己身上?
    • 从后往前遍历子控件,重复前面的两个步骤
    • 如果没有符合条件的子控件,那么就自己最适合处理

    原理

    // point:是方法调用者坐标系上的触摸点的位置
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        // 1.判断下能否接收触摸事件
        if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.0) return nil;
    
        // 2.判断下点在不在控件上
        if ([self pointInside:point withEvent:event] == NO) return nil;
    
        // 3.从后往前遍历子控件
        int count = (int)self.subviews.count;
    
        for (int 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) {
                return fitView;
            }
    
        }
    
        // 表示没有比自己更合适的view
        return self;
    
    }
    

    事件传递的完整过程

    • 1> 先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件。

    • 2> 调用最合适控件的touches….方法

    • 3> 如果调用了[super touches….];就会将事件顺着响应者链条往上传递,传递给上一个响应者

    • 4> 接着就会调用上一个响应者的touches….方法

    如何判断上一个响应者

    • 1> 如果当前这个view是控制器的view,那么控制器就是上一个响应者

    • 2> 如果当前这个view不是控制器的view,那么父控件就是上一个响应者

    响应者链的事件传递过程

    • 如果view的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图
    • 在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
    • 如果window对象也不处理,则其将事件或消息传递给UIApplication对象
    • 如果UIApplication也不能处理该事件或消息,则将其丢弃

    响应者链条示意图

    • 响应者链条:是由多个响应者对象连接起来的链条
    • 作用:能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象处理。
    • 响应者对象:能处理事件的对象 

    监听触摸事件的做法

    • 如果想监听一个view上面的触摸事件,之前的做法是 自定义一个view
    • 实现view的touches方法,在方法内部实现具体处理代码
    • 通过touches方法监听view触摸事件,有很明显的几个缺点
    • 1.必须得自定义view
    • 由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件
    • 不容易区分用户的具体手势行为

    UIGestureRecognizer

    • 为了完成手势识别,借助于手势识别器----UIGestureRecognizer
    • 利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势
    UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势
    UITapGestureRecognizer(敲击)
    UIPinchGestureRecognizer(捏合,用于缩放)
    UIPanGestureRecognizer(拖拽)
    UISwipeGestureRecognizer(轻扫)
    UIRotationGestureRecognizer(旋转)
    UILongPressGestureRecognizer(长按)

    Demo:
    https://github.com/SYLing/Gesture.git
     
  • 相关阅读:
    MVC3、如何应用EntityFramework 连接MySql 数据库 Kevin
    DEV EXPRESS Summary Footer 不显示 Kevin
    装饰模式 Kevin
    Dev 控件 GridControl 控件 二次绑定数据源的问题。 Kevin
    System.InvalidOperationException 异常 Kevin
    LINQ to XML Kevin
    代理模式——代码版“吊丝的故事” Kevin
    VS2012 中的设备 面板 Kevin
    maven 学习笔记(三)创建一个较复杂的 eclipse+android+maven 工程
    maven 学习笔记(一)eclipse+android+maven
  • 原文地址:https://www.cnblogs.com/ShaoYinling/p/4639643.html
Copyright © 2011-2022 走看看