iOS - 手势与触摸

简介

在iOS中不是任何对象都能处理事件,只有继承了UIResponser的对象才能接收并处理事件。我们称之为“响应者对象”。
UIView是UIResponder的子类,可以通过覆盖下列4个方法处理不同的触摸事件。

 //当一个或多个⼿手指触碰屏幕时
 //如果两根手指同时触摸某个视图,那么touchesBegan:withEvent:的第一个参数是包含两个UITouch实例的NSSet对象。
 //如果这两根手指一前一后分开触摸同一个视图,那么视图会收到两个独立的touchesBegan:withEvent:消息,并且每个NSSet对象中只包含一个UITouch对象。
 - (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

当用户触摸屏幕时,事件会被封装成一个event实例,包含了用户触摸的相关信息(位置信息),event实例中包含着若干个UITouch实例,touch数量表示用户的手指数量。
UIView不接收处理事件的三种情况

  • 不接收用户交互:userInteractionEnabled = NO。
  • 隐藏:hidden = YES。
  • 透明:alpha = 0~0.01。

事件类型

触摸事件、运动事件、远程遥控事件、物理按钮事件。

typedef NS_ENUM(NSInteger, UIEventType) {
    UIEventTypeTouches,
    UIEventTypeMotion,
    UIEventTypeRemoteControl,
    UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),
};

UITouch

属性和方法 解释
window 触摸产生时所处的窗口。由于窗口可能发生变化,当前所在的窗口不一定是最开始的窗口。
view 触摸产生时所处的视图。由于视图可能发生变化,当前视图不一定是最初的视图。
tapCount 轻击(Tap)操作和鼠标单击操作类似,tapCount表⽰短时间内轻击屏幕的次数。因此可以根据tapCount判断单击、双击或更多的轻击
timestamp 时间戳记录了触摸事件产⽣或变化时的时间。单位是秒
phase 触摸事件在屏幕上有一个周期,即触摸开始、触摸点移动、触摸结束,还有中途取消。而通过phase可以查看当前触摸事件在一个周期中所处的状态。phase是UITouchPhase类型的,是一个枚举配型。
-(CGPoint)locationInView:(UIView *)view: 函数返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,返回的位置是针对view坐标系的
-(CGPoint)previousLocationInView:(UIView *)view: 该方法记录了前一个坐标值,函数返回也是一个CGPoint类型的值表⽰触摸view视图上的位置,返回的位置是针对view坐标系的

UITouchPhase

typedef NS_ENUM(NSInteger, UITouchPhase) {
    UITouchPhaseBegan,             //触摸开始
    UITouchPhaseMoved,             //接触点移动
    UITouchPhaseStationary,        //接触点无移动
    UITouchPhaseEnded,             //接触结束
    UITouchPhaseCancelled,         //接触取消
}

事件传递

从事件发生到其处理的对象,传递要经过特殊的一段过程。当用户点击设备屏幕时,iOS捕捉到一系列的触摸,将其打包到UIEvent对象中并放置到应用程序活动事件队列中。UIApplication对象从事件队列中取出最前面的事件并将其分发。通常发送事件给应用程序的主窗口UIWindow实例,主窗口会调用hitTest:withEvent:方法在视图继承树中找到一个最合适的子视图来处理触摸事件,该子视图即为hit-test视图。
如果hit-test视图不处理收到的事件消息,UIKit则将事件转发到响应者链中的下一个响应者,看其是否能对该消息进行处理。

响应者链

响应者对象是一个能接收并处理事件的对象。UIResponser是所有响应者对 象的基类。该基类定义了一系列编程接口,不但为事件处理进行服务而且还提供了通用的响应行为处理。UIApplication, UIView(包括 UIWindow),UIViewController都直接或间接的继承自UIResponser,所有的这些类的实例都是响应者对象。响应者链表示一系列的响应者对象。

  • 当用户与视图交互时,将消息传递给视图控制器,如果不存在控制器,传递给父视图。
  • 如果不处理该消息,则继续将消息向上传递。
  • 最上层的视图如果也不处理,将事件交予Window对象。
  • 最后交由UIApplication实 例,如果不处理,丢弃事件。

UIGestureRecognizer(手势识别器)

UIGestureRecognizer类,用于检测、识别用户使用设备时所用的手势。它是一 个抽象类,定义了所有手势的基本行为。
手势识别的状态

typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
    UIGestureRecognizerStatePossible,//没有触摸事件发生,所有手势识别的默认状态。
    UIGestureRecognizerStateBegan,//一个手势已经开始但尚未改变或者完成时。
    UIGestureRecognizerStateChanged,//手势状态改变
    UIGestureRecognizerStateEnded,//手势完成
    UIGestureRecognizerStateCancelled,//手势取消,恢复至Possible状态
    UIGestureRecognizerStateFailed,//手势失败,恢复至Possible状态
    UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded//识别到手势识别
};

UIGestureRecognizer子类

UITapGestureRecognizer(轻击)

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleGesture:)];
    [view addGestureRecognizer:singleTap];
    
- (void)singleGesture:(UITapGestureRecognizer *) tap{
    NSLog(@"单击");
} 

如果是双击事件,需设置tap.numberOfTapsRequired = 2;
tap.numberOfTouchesRequired = 1; //点击手指数
UIPinchGestureRecognizer(捏合)

    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]
                                         initWithTarget:self action:@selector(pinch:)];
    [view addGestureRecognizer:pinch];

static float scale = 0;
- (void)pinch:(UIPinchGestureRecognizer *)_pinch {
    if(_pinch.state == UIGestureRecognizerStateEnded) {
        return;
    }
    if(scale == 0) {
        if(_pinch.scale > 0){
            NSLog(@"放⼤");
        }else{
            NSLog(@"缩⼩");
        }
    }else{
        if(scale - _pinch.scale < 0){
            NSLog(@"放⼤");
        }else{
            NSLog(@"缩⼩");
        }
    }
    scale = _pinch.scale;
}

UIPanGestureRecognizer(平移)

UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[view addGestureRecognizer:panGesture];

 - (void)pan:(UIPanGestureRecognizer *)_pan {
    CGPoint point = [_pan locationInView:self.view];
    tempView.center = point;
}

UISwipeGestureRecognizer(轻扫)

    UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
    swipeGesture.direction = UISwipeGestureRecognizerDirectionUp;
    [view addGestureRecognizer:swipeGesture];

UIRotationGestureRecognizer(旋转)

UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
[view addGestureRecognizer:rotationGesture];

 - (void)rotation:(UIRotationGestureRecognizer *)_rotation {
    float degress = _rotation.rotation*(180/M_PI);
    tempView.transform = CGAffineTransformRotate(tempView.transform,
degress/1000);
}

UILongPressGestureRecognizer(长按)

UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; 
longPressGesture.minimumPressDuration = 3;
[view addGestureRecognizer:longPressGesture]; 

 - (void)longPress:(UILongPressGestureRecognizer *)_longPress {
    NSLog(@"long press : %u", [_longPress state]);
}

UILongPressGestureRecognizer的state属性:
开始:UIGestureRecognizerStateBegan
改变:UIGestureRecognizerStateChanged
结束:UIGestureRecognizerStateEnded
取消:UIGestureRecognizerStateCancelled
失败:UIGestureRecognizerStateFailed

发布了38 篇原创文章 · 获赞 5 · 访问量 9052

猜你喜欢

转载自blog.csdn.net/zj382561388/article/details/103351716