「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
iOS中的事件
- 在用户使用APP过程中,会产生各种各样的事件,可以分为三大类
- 触摸事件(如点击...)
- 加速器事件(如摇一摇...)
- 远程控制事件(如耳机可以控制手机音量...)
响应者对象(UIResponder)
说到触摸事件,首先需要了解一个概念:响应者对象
-
在iOS中不是任何对象都能处理事件,只有继承了
UIResponder
的对象才能接收并处理事件,通常被称为“响应者对象”。如UIApplication
、UIViewController
、UIView
等等 -
UIResponder
内部提供了以下方法来处理事件 -
触摸事件
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; - (void)touchesCancelled:(NSSet<UITouch *> *)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; 复制代码
UIView 的触摸事件处理
-
UIView
是UIResponder
的子类,可以覆盖以下4个方法处理不同的触摸事件 -
一根或者多根手指开始触摸
view
,系统会自动调用view
的下面方法- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event; 复制代码
-
一根或者多根手指在
view
上移动,系统会自动调用view
的下面方法- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; 复制代码
-
一根或者多根手指离开
view
,系统会自动调用view
的下面方法- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; 复制代码
-
触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用
view
的下面方法- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event; 复制代码
UITouch
- 当用户用一根手指触摸屏幕时,会创建一个与手指关联的
UITouch
对象 - 一根手指对应一个
UITouch
对象 UITouch
的作用:保存着跟手指相关的信息,比如触摸的位置、时间、阶段- 当手指移动时,系统会更新同一个
UITouch
对象,使之能够一直保存该手指在的触摸位置 - 当手指离开屏幕时,系统会销毁相应的
UITouch
对象 UITouch
相关属性window
触摸产生时所处的窗口view
触摸产生时所处的视图tapCount
短时间内按屏幕的次数,根据tapCount
判断单击、双击或更多点击timestamp
记录了触摸事件产生或变化的时间,单位是秒phase
当前触摸事件所处的状态
UITouch
相关方法-
返回值表示触摸在
view
上的位置,这里返回的位置是针对view的坐标系的(以view
的左上角为原点(0,0)),调用时如果传入的view
参数是nil
的话,返回的时触摸点在window
的位置[touch locationInView:view]; 复制代码
-
该方法记录了上一个点的位置
[touch previousLocationInView:view]; 复制代码
-
注:
iPhone开发中,要避免使用双击事件
如果要在一个 view
中监听多个手指,需要设置属性
//需要view支持多个手
view.multipleTouchEnabled = YES;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"%ld",(long)touches.count); //2
}
复制代码
UIEvent
- 每产生一个事件,就会产生一个
UIEvent
对象 UIEvent
被称为事件对象,用于记录事件产生的时刻和类型UIEvent
相关属性- 事件类型
type
枚举类型(触摸事件、加速器事件、远程控制事件)subtype
timestamp
事件产生时间
- 事件类型
UIEvent
相关方法UIEvent
提供相应方法用于获取在某个view
上面的接触对象(UITouch
)
简单示例
实现需求:一个按钮可以在屏幕任务拖拽
1.自定义一个 UIImageView
@implementation InputImageView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
UIImage *image = [UIImage imageNamed:@"inputButton"];
self.image = image;
self.userInteractionEnabled = YES;
}
return self;
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = touches.anyObject;
//获取当前点
CGPoint currentPoint = [touch locationInView:self];
//获取上一个点的位置
CGPoint previousPoint = [touch previousLocationInView:self];
//获取x轴偏移量
CGFloat offsetX = currentPoint.x - previousPoint.x;
CGFloat offsetY = currentPoint.y - previousPoint.y;
//修改view的位置
self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);
}
@end
复制代码
2.实际调用
#import "ViewController.h"
#import "InputImageView.h"
@interface ViewController ()
@property (nonatomic,strong) InputImageView *redView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
InputImageView *inputImageView = [[InputImageView alloc]initWithFrame:CGRectMake(150, 150, 56, 56)];
[self.view addSubview:inputImageView];
}
@end
复制代码