您的位置:首页 > 移动开发 > IOS开发

iOS开发学习之触摸事件和手势识别

2015-11-14 15:25 459 查看


iOS开发学习之触摸事件和手势识别

 

iOS的输入事件
触摸事件
手势识别
手机摇晃

一、iOS的输入事件

 

触摸事件(滑动、点击)

运动事件(摇一摇、手机倾斜、行走),不需要人为参与的

远程控制事件(耳机控制手机声音)

1⃣️iOS事件对象都是UIEvent类的实例

UIEvent类对事件类型定义了enum常量:
typedef NS_ENUM(NSInteger, UIEventType){
     UIEventTypeTouches,
     UIEventTypeMotion,
     UIEventRemoteControl,
};

触摸事件必须是继承UIResponser的

 

二、触摸事件

1⃣️UIView,有4种处理不同的触摸事件

UIView是UIResponder的子类,可以覆盖下列4个方法处理不同的触摸事件。

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

 

#pragma mark - UITouch事件

#pragma mark 触摸开始

1 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2 {
3     NSLog(@"触摸开始");
4     for (UITouch *touch in touches) {
5         NSLog(@"%@", touch);
6     }
7 }


 

#pragma mark 触摸移动

1 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
2 {
3     NSLog(@"触摸移动Touch对象个数:%d",[touches count]);
4     // 要移动界面上黄颜色的视图
5
6     // 1. 得到当前手指的位置
7     UITouch *touch = [touches anyObject];
8     CGPoint location = [touch locationInView:self.view];
9     // 2. 得到上一次手指的位置
10     CGPoint preLocation = [touch previousLocationInView:self.view];
11     // 3. 计算两个位置之间的偏移
12     CGPoint offset = CGPointMake(location.x - preLocation.x, location.y - preLocation.y);
13     // 4. 使用计算出来的偏移量,调整视图的位置
14     [_demoView setCenter:CGPointMake(_demoView.center.x + offset.x, _demoView.center.y + offset.y)];
15
16     // 完整的UITouch事件调试方法
17     NSLog(@"触摸移动");
18     for (UITouch *touch in touches) {
19         NSLog(@"%@", touch);
20     }
21 }
22
23 #pragma mark 触摸结束
24 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
25 {
26     // 完整的UITouch事件调试方法
27     NSLog(@"触摸完成");
28     for (UITouch *touch in touches) {
29         NSLog(@"%@", touch);
30     }
31 }
32
33 #pragma mark 触摸中断
34 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
35 {
36     // 完整的UITouch事件调试方法
37     NSLog(@"触摸中断");
38     for (UITouch *touch in touches) {
39         NSLog(@"%@", touch);
40     }
41 }


 

Swift

1 override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
2         println("touchesBegan")
3
4         //获取touches数量
5         let numTouches = touches.count
6
7         //获取点击屏幕的次数
8         let tapTouches = (touches as NSSet).anyObject()?.tapCount
9
10         //获取事件发生时间
11         let timestamp = event.timestamp
12
13         //获取当前相对于self.view的坐标
14         let locationPoint = (touches as NSSet).anyObject()?.locationInView(self.view)
15
16         //获取上一次相对于self.view的坐标
17         let previousPoint = (touches as NSSet).anyObject()?.previousLocationInView(self.view)
18
19         //允许使用手势
20         self.view.userInteractionEnabled = true
21
22         //支持多点触摸
23         self.view.multipleTouchEnabled = true
24
25         println("\(tapTouches)")
26
27
28         //判断如果有两个触摸点
29         if touches.count == 2
30         {
31             //获取触摸集合
32             let twoTouches = (touches as NSSet).allObjects
33
34             //获取触摸数组
35             let first:UITouch = twoTouches[0] as! UITouch //第1个触摸点
36             let second:UITouch = twoTouches[1]as! UITouch //第2个触摸点
37
38             //获取第1个点相对于self.view的坐标
39             let firstPoint:CGPoint = first.locationInView(self.view)
40
41             //获取第1个点相对于self.view的坐标
42             let secondPoint:CGPoint = second.locationInView(self.view)
43
44             //计算两点之间的距离
45             let deltaX = secondPoint.x - firstPoint.x;
46             let deltaY = secondPoint.y - firstPoint.y;
47             let initialDistance = sqrt(deltaX*deltaX + deltaY*deltaY )
48
49             println("两点间距离是:\(initialDistance)")
50         }
51     }
52
53     //手指在移动
54 //    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
55
56     //2015年5月2后修改
57     override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
58
59         println("touchesMoved")
60     }
61
62     //触摸结束
63 //    override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
64
65     //2015年5月2后修改
66     override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
67
68         println("touchesEnded")
69     }
70
71     //触摸意外终止
72     //模拟器演示:鼠标拖动的同时,按键盘command+shift+h 相当于点击手机home键,退出应用,触发touchesCancelled事件,在打电话、等情况下也会触发
73 //    override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
74
75     //2015年5月2后修改
76     override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
77
78         println("touchesCancelled")
79     }
80


 

 

2⃣️触摸事件的处理

如果hit-test视图无法处理事件,则通过响应者链向上传递

1.如果hit-test视图的控制器存在,就传递给控制器;如果控制器不存在,则将其传递给它的父视图

2.如果视图或它的控制器无法处理收到的事件或消息,则将其传递给该视图的父视图

3.每一个在视图继承树中的上层视图如果不能处理收到的事件或消息,则重复上面的步骤1,2

4.在视图继承树的最上层视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给窗口对象进行处理

5. 如果窗口对象也不能进行处理,则其将事件或消息传递给UIApplication对象

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

当用户点击屏幕时,会产生一个UITouch对象传递给UIApplication,然后由window负责查找最适合相应触摸事件的视图对象(hitTest,pointInside)

找到合适的视图之后,Touch方法由对应的视图完成,上级视图不再接管

3⃣️不接受处理事件的三种方法

不接收用户交互:userInteractionEnabled = NO;

隐藏:hidden = YES;

透明:alpha = 0~0.01

 

三、手势识别

1⃣️iOS目前支持的手势识别(6种)

UITapGestureRecognizer(点按)

UIPinchGestureRecognizer(捏合)

UIPanGestureRecognizer(拖动)

UISwipeGestureRecognizer(轻扫)

UIRotationGestureRecognizer(旋转)

UILongPressGestureRecognizer(长按)

2⃣️手势识别的使用方法(4步)

通常在视图加载的时候定义(UIGestureRecognizer是抽象类,需要实例化使用)

创建手势识别实例

设置手势识别属性,例如手指数量,方向等

将手势识别附加到指定的视图之上

编写手势触发响应方法

3⃣️手势识别的状态(7个)

   1.  // 没有触摸事件发生,所有手势识别的默认状态

    UIGestureRecognizerStatePossible,

    // 一个手势已经开始但尚未改变或者完成时

    UIGestureRecognizerStateBegan,

    // 手势状态改变

    UIGestureRecognizerStateChanged,

    // 手势完成

    UIGestureRecognizerStateEnded,

    // 手势取消,恢复至Possible状态

    UIGestureRecognizerStateCancelled, 

    // 手势失败,恢复至Possible状态

    UIGestureRecognizerStateFailed,

    // 识别到手势识别

    UIGestureRecognizerStateRecognized =UIGestureRecognizerStateEnded 

  2.手势识别的属性

state——手势状态view——手势发生视图

常用方法

locationInView 获得手势发生对应视图所在位置

1 - (void)viewDidLoad
2 {
3     [super viewDidLoad];
4
5     // 根据实例化方法,我们知道:
6     // 1.有一个处理消息的对象,应该是self
7     // 2.我们需要定义一个方法,当手势识别检测到的时候,运行
8     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction:)];
9     // setNumberOfTapsRequired 点按次数
10     [tap setNumberOfTapsRequired:1];
11     // setNumberOfTouchesRequired 点按的手指数量
12     [tap setNumberOfTouchesRequired:1];
13     // 把手势识别增加到视图上
14     [self.demoView addGestureRecognizer:tap];
15
16
17     UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinchAction:)];
18     [self.demoView addGestureRecognizer:pinch];
19
20
21     UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotationAction:)];
22     [self.demoView addGestureRecognizer:rotation];
23
24
25     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panAction:)];
26     [self.demoView addGestureRecognizer:pan];
27
28
29     UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressAction:)];
30     [self.demoView addGestureRecognizer:longPress];
31
32
33     // 向左扫
34     UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
35     [swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
36     [self.view addGestureRecognizer:swipeLeft];
37     // 向右扫
38     UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
39     [swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
40     [self.view addGestureRecognizer:swipeRight];
41     // 向上扫
42     UISwipeGestureRecognizer *swipeTop = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
43     [swipeTop setDirection:UISwipeGestureRecognizerDirectionUp];
44     [self.view addGestureRecognizer:swipeTop];
45     // 向下扫
46     UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeAction:)];
47     [swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
48     [self.view addGestureRecognizer:swipeDown];
49 }
50
51 - (void)didReceiveMemoryWarning
52 {
53     [super didReceiveMemoryWarning];
54     // Dispose of any resources that can be recreated.
55 }


#pragma mark - 轻扫手势

1 - (void)swipeAction:(UISwipeGestureRecognizer *)sender
2 {
3     NSLog(@"%d", sender.direction);
4     switch (sender.direction) {
5         case UISwipeGestureRecognizerDirectionLeft:
6             NSLog(@"向左扫");
7             break;
8         case UISwipeGestureRecognizerDirectionRight:
9             NSLog(@"向右扫");
10             break;
11         case UISwipeGestureRecognizerDirectionUp:
12             NSLog(@"向上扫");
13             break;
14         case UISwipeGestureRecognizerDirectionDown:
15             NSLog(@"向下扫");
16             break;
17         default:
18             break;
19     }
20 }


#pragma mark - 长按手势

1 - (void)longPressAction:(UILongPressGestureRecognizer *)sender
2 {
3     // 我们可以利用demoView的Tag属性,默认时tag=0
4     // 如果tag=0,我们放大一倍,否则,我们缩小一半
5     CGFloat scale;
6     if (_demoView.tag == 0) {
7         scale = 2.0;
8         _demoView.tag = 1;
9     } else {
10         scale = 0.5;
11         _demoView.tag = 0;
12     }
13
14     sender.view.transform = CGAffineTransformScale(sender.view.transform, scale, scale);
15 }
16


 

#pragma mark - 拖放手势

1 - (void)panAction:(UIPanGestureRecognizer *)sender
2 {
3     // 在拖放手势中是需要考虑手指的状态的UIGestureRecognizerState
4     // 在拖放手势中使用的状态是UIGestureRecognizerStateChanged
5     // 通常在使用拖放手势的时候,当手指离开的时候,应该做一个很小的动作,提醒用户拖放完成
6     if (sender.state == UIGestureRecognizerStateChanged) {
7         // locationInView
8         [_demoView setCenter:[sender locationInView:self.view]];
9     } else if (sender.state == UIGestureRecognizerStateEnded) {
10         [_demoView setBackgroundColor:[UIColor yellowColor]];
11     }
12 }


#pragma mark - 旋转手势

1 - (void)rotationAction:(UIRotationGestureRecognizer *)sender
2 {
3     sender.view.transform = CGAffineTransformRotate(sender.view.transform, sender.rotation);
4
5     // 和捏合操作类似,旋转角度同样需要方福伟
6     sender.rotation = 0.0f;
7 }
8
9 #pragma mark - 捏合手势
10 - (void)pinchAction:(UIPinchGestureRecognizer *)sender
11 {
12     // 有关转换的内容,我们在后续动画部分再继续
13     sender.view.transform = CGAffineTransformScale(sender.view.transform, sender.scale, sender.scale);
14
15     // 缩放功能很简单,但是不要忘记将比例复位
16     sender.scale = 1.0f;
17     NSLog(@"捏我了");
18 }
19
20 #pragma mark - 点按手势
21 - (void)tapAction:(UITapGestureRecognizer *)sender
22 {
23
24     NSLog(@"点我了 %@", sender);
25 }
26
27 #pragma mark - 手势触摸事件
28 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
29 {
30     NSLog(@"触摸事件!");
31     // 1. 先取出UITouch对象
32     // 2. 判断响应点击的UIView是不是我们需要的
33     UITouch *touch = [touches anyObject];
34     if ([touch view] == _imageView) {
35         NSLog(@"点到图像了!");
36     }
37 }


Swift:

添加手势

1         //点击事件
2         var atap = UITapGestureRecognizer(target: self, action: "tapDo:")
3         self.view.addGestureRecognizer(atap)
4         atap.numberOfTapsRequired = 1 //单击次数
5         atap.numberOfTouchesRequired = 1 //手指个数
6
7         //拖动事件
8         var aPan = UIPanGestureRecognizer(target: self, action: "handlenPan:")
9         self.view.addGestureRecognizer(aPan)
10         aPan.minimumNumberOfTouches = 1 //最少手指个数
11         aPan.maximumNumberOfTouches = 3 //最多手指个数
12
13         //长按事件
14         var aLongPress = UILongPressGestureRecognizer(target: self, action: "longPress:")
15         self.view.addGestureRecognizer(aLongPress)
16         aLongPress.minimumPressDuration = 1 //需要长按的时间,最小0.5s
17
18         //捏合事件
19         var aPinch = UIPinchGestureRecognizer(target: self, action: "pinchDo:")
20         self.view.addGestureRecognizer(aPinch)
21
22         //旋转事件
23         var aRotation = UIRotationGestureRecognizer(target: self, action: "rotatePiece:")
24         self.view.addGestureRecognizer(aRotation)
25
26         //轻扫事件--左轻扫
27         var leftSwipe = UISwipeGestureRecognizer(target: self, action: "leftSwipe:")
28         self.view.addGestureRecognizer(leftSwipe)
29         leftSwipe.direction =  UISwipeGestureRecognizerDirection.Left
30
31         //轻扫事件--右轻扫
32         var rightSwipe = UISwipeGestureRecognizer(target: self, action: "rightSwipe:")
33         self.view.addGestureRecognizer(rightSwipe)
34         rightSwipe.direction =  UISwipeGestureRecognizerDirection.Right
35
36         //轻扫事件--上轻扫
37         var upSwipe = UISwipeGestureRecognizer(target: self, action: "upSwipe:")
38         self.view.addGestureRecognizer(upSwipe)
39         upSwipe.direction =  UISwipeGestureRecognizerDirection.Up
40
41         //轻扫事件--下轻扫
42         var downSwipe = UISwipeGestureRecognizer(target: self, action: "downSwipe:")
43         self.view.addGestureRecognizer(downSwipe)
44         downSwipe.direction =  UISwipeGestureRecognizerDirection.Down
45     }


实现

1
2     //手势
3
4     //点击事件
5     func tapDo(sender:UITapGestureRecognizer)
6     {
7
8         println("点击事件")
9     }
10
11     //拖动事件
12     func handlenPan(sender:UIPanGestureRecognizer)
13     {
14         println("拖动事件")
15
16         if sender.state == .Began
17         {
18             //拖动开始
19         }
20         else if sender.state == .Changed
21         {
22             //拖动过程
23         }
24         else if sender.state == .Ended
25         {
26             //拖动结束
27         }
28     }
29
30     //长摁事件
31     func longPress(sender:UILongPressGestureRecognizer)
32     {
33         println("长摁事件")
34
35
36     }
37
38     //捏合事件
39     func pinchDo(sender:UIPinchGestureRecognizer)
40     {
41         println("捏合")
42     }
43
44     //旋转事件
45     func rotatePiece(sender:UIRotationGestureRecognizer)
46     {
47         println("旋转")
48     }
49
50
51     //轻扫事件--左轻扫
52     func leftSwipe(sender:UISwipeGestureRecognizer)
53     {
54         println("左轻扫")
55     }
56
57     //轻扫事件--右轻扫
58     func rightSwipe(sender:UISwipeGestureRecognizer)
59     {
60         println("右轻扫")
61     }
62
63     //轻扫事件--上轻扫
64     func upSwipe(sender:UISwipeGestureRecognizer)
65     {
66         println("上轻扫")
67     }
68
69     //轻扫事件--下轻扫
70     func downSwipe(sender:UISwipeGestureRecognizer)
71     {
72         println("下轻扫")
73     }


 

 

四、手机摇晃

1 1. 新建摇晃监听视图ShakeListenerView,并且设置canBecomeFirstResponder返回YES
2 - (BOOL)canBecomeFirstResponder
3 {
4     return YES;
5 }
6 2. 在Storyboard中将ViewController的View的Class设置为:ShakeListenerView
7 3. 在ViewController.m文件中增加:viewDidAppear和viewDidDisappear在视图出现和消失时成为/撤销第一响应者身份
8 4. 在视图控制器中增加手势监听方法:
9 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
10 {
11     if (event.subtype == UIEventSubtypeMotionShake) {
12         NSLog(@"shake phone");
13     }
14 }
15 16 #pragma mark - 要让ViewController支持摇晃,需要写三个方法
17 // 1. 成为第一响应者,视图一出现时,就应该成为第一响应者
18 - (void)viewDidAppear:(BOOL)animated
19 {
20     [self.view becomeFirstResponder];
21     // 不要忘记去实现父类方法
22     [super viewDidAppear:animated];
23 }
24
25 // 2. 注销第一响应者,视图要关闭的时候,注销
26 - (void)viewDidDisappear:(BOOL)animated
27 {
28     [self.view resignFirstResponder];
29     // 不要忘记去实现父类方法
30     [super viewDidDisappear:animated];
31 }
32
33 // 3. 监听并处理移动事件,判断是否摇晃了手机
34 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
35 {
36     if (motion == UIEventSubtypeMotionShake) {
37         NSLog(@"摇啊摇,摇到外婆桥!!!");
38     }
39 }


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: