ios事件处理

UITouch相关:

3大事件:触摸事件,加速计事件,远程控制事件
响应者对象:只有继承了UIResponser的对象才能接收并处理事件
UIResponser内部提供以下方法处理事件:
触摸事件(UIView)
一根或者多根手指开始触摸view,系统会自动调用view的下面方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

一根或者多根手指在view上移动,系统会自动调用view的下面方法(随着手指的移动,会持续调用该方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

一根或者多根手指离开view,系统会自动调用view的下面方法
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用view的下面方法
(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
提示:touches中存放的都是UITouch对象


加速计事件
- (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对象,使之能够一直保存该手指的触摸位置。
当手指离开屏幕时,系统会销毁相应的UITouch对象

View的拖拽:
// 一个完整的触摸过程
// touchesBegan -> touchesMoved -> touchesEnded

/*
    NSArray 集合 有序
    NSSet 无序

 */

// 触摸开始
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 获取一个UITouch
    UITouch *touch = [touches anyObject];
    
//     NSLog(@"%s----%d",__func__,touches.count);//多根手指
//    NSLog(@"%d",touch.tapCount);//短时间内点击的次数,可以判断当前用户是单击还是双击
//    NSLog(@"%d",touch.phase);//<span style="color:#595959;">当前触摸事件所处的状态</span><span style="color:#4F81BD;">,</span>可以判断当前手指就按下,移动,还是抬起
}
// 手指移动
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 获取一个UITouch
    UITouch *touch = [touches anyObject];
    //[touch locationInView:view ] 获取 
    // 获取当前的位置
    CGPoint current = [touch locationInView:self];
    // 获取上一个点
    CGPoint pre = [touch previousLocationInView:self]; 
    // x轴偏移量
    CGFloat offsetX = current.x - pre.x;
    CGFloat offsetY = current.y - pre.y;
    NSLog(@"%@",NSStringFromCGPoint(current));    
    // 获取视图的center
    CGPoint center = self.center;
    center.x += offsetX;
    center.y += offsetY;
    self.center = center;
}

// 触摸结束
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 获取一个UITouch
    UITouch *touch = [touches anyObject];
//      NSLog(@"%d",touch.phase);
//    NSLog(@"%s----%p",__func__,touch);
}

// 触摸被打断 比如打电话过来
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    
}


UITouch中常用方法:
<pre name="code" class="objc">- (CGPoint)locationInView:(UIView *)view;
返回值表示触摸在view上的位置
这里返回的位置是针对<span style="color:#FF0000;">view</span>的坐标系的(以view的左上角为原点(0, 0))
调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置

- (CGPoint)previousLocationInView:(UIView *)view;
该方法记录了前一个触摸点的位置

 

事件的产生和传递:

发生触摸事件后,系统会将该事件加入到一个由 UIApplication 管理的事件 队列(先产生先处理)
UIApplication 会从事件队列中 取出最前面的 事件,并将事件分发下去以便处 理,通常,先发送事件给应用程序的主窗 口( keyWindow
主窗口会在视图层次结构中 找到一个最合适的视图来处理触摸事件 ,但是这仅仅是整个事件处理过程的第一步
找到合适的视图控件后,就会调用视图控件的 touches 方法来作具体的事件处理触摸事件的传递是从父控件传递到子控件
点击了绿色的 view

UIApplication->UIWindow-> 白色->绿色

点击了蓝色的 view

UIApplication->UIWindow-> 白色->橙色->

点击了黄色的 view

UIApplication->UIWindow-> 白色->橙色-> 蓝色->黄色

如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸 事件 ( 掌握 )
如何找到最合适的控件来处理事件?
1> 自己是否能接收触摸事件?否,事件传递到此结束
2> 触摸点是否在自己身上?否,事件传递到此结束
3> 从后往前遍历子控件(需要递归的遍历子控件,看子控件能否处理),重复前面的两个步骤
4> 如果没有符合条件的子控件,那么就自己最适合处理

UIView不接收事件三种情况:
1. 不接收用户交互

userInteractionEnabled =NO

2. 隐藏

hidden = YES

3. 透明

alpha = 0.0~0.01

提示UIImageViewuserInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的

hitTest方法的原理:UIApplication sharedApplication].keyWindow hitTest:CGPoint withEvent:(UIEvent *)hitTest:wihtEvent1,看窗口能否接收,如果不能retrun nil;自己不能接收事件,也不能处理事件,而且也不能把事件传递给子控件2,判断点在不在窗口上 ,如果点在窗口上,意味着窗口满足是合适的view3,白色的view
触摸事件的监听:
如果想监听一个view上面的触摸事件,之前的做法是
自定义一个view
实现view的touches方法,在方法内部实现具体处理代码

通过touches方法监听view触摸事件,有很明显的几个缺点
必须得自定义view
由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件
不容易区分用户的具体手势行为

iOS 3.2之后,苹果推出了手势识别功能(Gesture Recognizer),在触摸事件处理方面,大大简化了开发者的开发难度
手势识别:
为了完成手势识别,必须借助于手势识别器----UIGestureRecognizer

利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势

UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势
UITapGestureRecognizer(敲击)
UIPinchGestureRecognizer(捏合,用于缩放)
UIPanGestureRecognizer(拖拽)
UISwipeGestureRecognizer(轻扫)
UIRotationGestureRecognizer(旋转)
UILongPressGestureRecognizer(长按)

每一个手势识别器的用法都差不多,比如UITapGestureRecognizer的使用步骤如下
创建手势识别器对象
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];

设置手势识别器对象的具体属性
// 连续敲击2次
tap.numberOfTapsRequired = 2;
// 需要2根手指一起敲击
tap.numberOfTouchesRequired = 2;

添加手势识别器到对应的view上
[self.iconView addGestureRecognizer:tap];

监听手势的触发
[tap addTarget:self action:@selector(tapIconView:)];

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



 用法示例:
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // pan
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
  
 //UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
  //tap.numberOfTpasRequired=2;//点按多少次才能触发手势
    //tap.numberOfTouchesRequired=2;//必须多少个手指触摸才能触发
        

    [_imagView addGestureRecognizer:pan];
}

- (void)pan:(UIPanGestureRecognizer *)pan
{
    // 获取手指移动的位置
    CGPoint trans = [pan translationInView:_imagView];
    
    _imagView.transform = CGAffineTransformTranslate(_imagView.transform, trans.x, trans.y);
    
    // 复位
    [pan setTranslation:CGPointZero inView:_imagView];
    NSLog(@"%@",NSStringFromCGPoint(trans));
    
}
#warning pinch
- (void)addPinch
{
    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
    // 设置代理的原因:想要同时支持多个手势
    pinch.delegate = self;
    [_imagView addGestureRecognizer:pinch];
    
}

- (void)pinch:(UIPinchGestureRecognizer *)pinch
{
    _imagView.transform = CGAffineTransformScale(_imagView.transform, pinch.scale, pinch.scale);
    
    // 复位
    pinch.scale = 1;
}

// Simultaneous:同时
// 默认是不支持多个手势
// 当你使用一个手势的时候就会调用
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}



#warning rotation
- (void)addRotation
{
    // rotation
    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
    rotation.delegate = self;
    [_imagView addGestureRecognizer:rotation];
}



- (void)rotation:(UIRotationGestureRecognizer *)rotation
{
    NSLog(@"%f",rotation.rotation);
//    _imagView.transform = CGAffineTransformMakeRotation(rotation.rotation);
    _imagView.transform = CGAffineTransformRotate(_imagView.transform, rotation.rotation);
    
    // 复位
    rotation.rotation = 0;
}

#warning Swipe
- (void)addSwipe
{
    // Swipe
    // 一个手势只能识别一个方向
    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
    swipe.direction = UISwipeGestureRecognizerDirectionRight;
    [_imagView addGestureRecognizer:swipe];
}

- (void)swipe:(UISwipeGestureRecognizer *)swipe
{
    NSLog(@"swipe");
}

#warning longPress
- (void)addLongPress
{
    // longPress
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
    
    [_imagView addGestureRecognizer:longPress];
}


- (void)longPress:(UILongPressGestureRecognizer *)longPress
{
    // 根据状态执行事件
    if (longPress.state == UIGestureRecognizerStateBegan) {
        
        NSLog(@"longPress");
    }
}


#warning tap
- (void)addTap
{
    // tap
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
    // 点按多少次才能触发手势
    //    tap.numberOfTapsRequired = 2;
    //
    //    // 必须多少个手指触摸才能触发手势
    //    tap.numberOfTouchesRequired = 2;
    
    tap.delegate = self;
    
    [_imagView addGestureRecognizer:tap];
}

// 这个触摸点能否触发手势
//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
//{
//    CGPoint currentPoint = [touch locationInView:_imagView];
//    
//    if (currentPoint.x < _imagView.bounds.size.width * 0.5) {
//        return NO;
//    }else{
//        
//        return YES;
//    }
//}

- (void)tap:(UITapGestureRecognizer *)tap
{
    NSLog(@"tap");
}


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值