iOS手势识别的详细使用方法(拖动,缩放,旋转,点击,手势依赖,自定义手势)

2025-05-29 0 67

手势识别在ios上非常重要,手势操作移动设备的重要特征,极大的增加了移动设备使用便捷性。

1、uigesturerecognizer介绍

手势识别在ios上非常重要,手势操作移动设备的重要特征,极大的增加了移动设备使用便捷性。

ios系统在3.2以后,为方便开发这使用一些常用的手势,提供了uigesturerecognizer类。手势识别uigesturerecognizer类是个抽象类,下面的子类是具体的手势,开发这可以直接使用这些手势识别

  • uitapgesturerecognizer
  • uipinchgesturerecognizer
  • uirotationgesturerecognizer
  • uiswipegesturerecognizer
  • uipangesturerecognizer
  • uilongpressgesturerecognizer

上面的手势对应的操作是:

  • tap(点一下)
  • pinch(二指往內或往外拨动,平时经常用到的缩放)
  • rotation(旋转)
  • swipe(滑动,快速移动)
  • pan (拖移,慢速移动)
  • longpress(长按)

uigesturerecognizer的继承关系如下:iOS手势识别的详细使用方法(拖动,缩放,旋转,点击,手势依赖,自定义手势)

2、使用手势的步骤

使用手势很简单,分为两步:

创建手势实例。当创建手势时,指定一个回调方法,当手势开始,改变、或结束时,回调方法被调用。

添加到需要识别的view中。每个手势只对应一个view,当屏幕触摸在view的边界内时,如果手势和预定的一样,那就会回调方法。

ps:一个手势只能对应一个view,但是一个view可以有多个手势。

建议在真机上运行这些手势,模拟器操作不太方便,可能导致你认为手势失效。

3、pan 拖动手势:

?

1

2

3

4

5

6

7

8
uiimageview *snakeimageview = [[uiimageview alloc] initwithimage:[uiimage imagenamed:@"snake.png"]];

snakeimageview.frame = cgrectmake(50, 50, 100, 160);

uipangesturerecognizer *pangesturerecognizer = [[uipangesturerecognizer alloc]

initwithtarget:self

action:@selector(handlepan:)];

[snakeimageview addgesturerecognizer:pangesturerecognizer];

[self.view setbackgroundcolor:[uicolor whitecolor]];

[self.view addsubview:snakeimageview];

新建一个imageview,然后添加手势

回调方法:

?

1

2

3

4

5

6

7

8
- (void) handlepan:(uipangesturerecognizer*) recognizer

{

cgpoint translation = [recognizer translationinview:self.view];

recognizer.view.center = cgpointmake(recognizer.view.center.x + translation.x,

recognizer.view.center.y + translation.y);

[recognizer settranslation:cgpointzero inview:self.view];

}

4、pinch缩放手势

?

1

2

3
uipinchgesturerecognizer *pinchgesturerecognizer = [[uipinchgesturerecognizer alloc]

initwithtarget:self

action:@selector(handlepinch:)];<p class="p1">[<span class="s1">snakeimageview</span> <span class="s2">addgesturerecognizer</span>:pinchgesturerecognizer];</p>

?

1

2

3

4

5
- (void) handlepinch:(uipinchgesturerecognizer*) recognizer

{

recognizer.view.transform = cgaffinetransformscale(recognizer.view.transform, recognizer.scale, recognizer.scale);

recognizer.scale = 1;

}

5、rotation旋转手势

?

1

2

3

4
uirotationgesturerecognizer *rotaterecognizer = [[uirotationgesturerecognizer alloc]

initwithtarget:self

action:@selector(handlerotate:)];

[snakeimageview addgesturerecognizer:rotaterecognizer];

?

1

2

3

4

5
- (void) handlerotate:(uirotationgesturerecognizer*) recognizer

{

recognizer.view.transform = cgaffinetransformrotate(recognizer.view.transform, recognizer.rotation);

recognizer.rotation = 0;

}

iOS手势识别的详细使用方法(拖动,缩放,旋转,点击,手势依赖,自定义手势)

添加了这几个手势后,运行看效果,程序中的imageview放了一个

/^\\/^\\
_|__| o|
\\/ /~ \\_/ \\
\\____|__________/ \\
\\_______ \\
`\\ \\ \\
| | \\
/ / \\
/ / \\\\
/ / \\ \\
/ / \\ \\
/ / _—-_ \\ \\
/ / _-~ ~-_ | |
( ( _-~ _–_ ~-_ _/ |
\\ ~-____-~ _-~ ~-_ ~-_-~ /
~-_ _-~ ~-_ _-~
~–______-~ ~-___-~

的图片,在模拟器上拖动是没问题的。缩放和旋转有点问题,估计是因为在模拟器上的模拟的两个接触点距离在imageview的边界外了,所以操作无效果。

建议在真机上运行这个手势。

在模拟器上缩放和选择的操作技巧:

可以把imageview的frame值设置大一点,按住alt键,按下触摸板(不按下不行),这样就可以旋转和缩放了。

6、添加第二个imagview并添加手势

记住:一个手势只能添加到一个view,两个view当然要有两个手势的实例了

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31
- (void)viewdidload

{

[super viewdidload];

uiimageview *snakeimageview = [[uiimageview alloc] initwithimage:[uiimage imagenamed:@"snake.png"]];

uiimageview *dragonimageview = [[uiimageview alloc] initwithimage:[uiimage imagenamed:@"dragon.png"]];

snakeimageview.frame = cgrectmake(120, 120, 100, 160);

dragonimageview.frame = cgrectmake(50, 50, 100, 160);

[self.view addsubview:snakeimageview];

[self.view addsubview:dragonimageview];

for (uiview *view in self.view.subviews) {

uipangesturerecognizer *pangesturerecognizer = [[uipangesturerecognizer alloc]

initwithtarget:self

action:@selector(handlepan:)];

uipinchgesturerecognizer *pinchgesturerecognizer = [[uipinchgesturerecognizer alloc]

initwithtarget:self

action:@selector(handlepinch:)];

uirotationgesturerecognizer *rotaterecognizer = [[uirotationgesturerecognizer alloc]

initwithtarget:self

action:@selector(handlerotate:)];

[view addgesturerecognizer:pangesturerecognizer];

[view addgesturerecognizer:pinchgesturerecognizer];

[view addgesturerecognizer:rotaterecognizer];

[view setuserinteractionenabled:yes];

}

[self.view setbackgroundcolor:[uicolor whitecolor]];

}

多添加了一条龙的view,两个view都能接收上面的三种手势。运行效果如下:iOS手势识别的详细使用方法(拖动,缩放,旋转,点击,手势依赖,自定义手势)

7、拖动(pan手势)速度(以较快的速度拖放后view有滑行的效果)
如何实现呢?

  • 监视手势是否结束
  • 监视触摸的速度
?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25
- (void) handlepan:(uipangesturerecognizer*) recognizer

{

cgpoint translation = [recognizer translationinview:self.view];

recognizer.view.center = cgpointmake(recognizer.view.center.x + translation.x,

recognizer.view.center.y + translation.y);

[recognizer settranslation:cgpointzero inview:self.view];

if (recognizer.state == uigesturerecognizerstateended) {

cgpoint velocity = [recognizer velocityinview:self.view];

cgfloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));

cgfloat slidemult = magnitude / 200;

nslog(@"magnitude: %f, slidemult: %f", magnitude, slidemult);

float slidefactor = 0.1 * slidemult; // increase for more of a slide

cgpoint finalpoint = cgpointmake(recognizer.view.center.x + (velocity.x * slidefactor),

recognizer.view.center.y + (velocity.y * slidefactor));

finalpoint.x = min(max(finalpoint.x, 0), self.view.bounds.size.width);

finalpoint.y = min(max(finalpoint.y, 0), self.view.bounds.size.height);

[uiview animatewithduration:slidefactor*2 delay:0 options:uiviewanimationoptioncurveeaseout animations:^{

recognizer.view.center = finalpoint;

} completion:nil];

}

代码实现解析:

  • 计算速度向量的长度(估计大部分都忘了)这些知识了。
  • 如果速度向量小于200,那就会得到一个小于的小数,那么滑行会很短
  • 基于速度和速度因素计算一个终点
  • 确保终点不会跑出父view的边界
  • 使用uiview动画使view滑动到终点

运行后,快速拖动图像view放开会看到view还会在原来的方向滑行一段路。

8、同时触发两个view的手势

手势之间是互斥的,如果你想同时触发蛇和龙的view,那么需要实现协议

uigesturerecognizerdelegate,

?

1

2
@interface viewcontroller : uiviewcontroller<uigesturerecognizerdelegate>

@end

并在协议这个方法里返回yes。

?

1

2

3

4
-(bool)gesturerecognizer:(uigesturerecognizer *)gesturerecognizer shouldrecognizesimultaneouslywithgesturerecognizer:(uigesturerecognizer *)othergesturerecognizer

{

return yes;

}

把self作为代理设置给手势:

?

1

2

3
pangesturerecognizer.delegate = self;

pinchgesturerecognizer.delegate = self;

rotaterecognizer.delegate = self;

这样可以同时拖动或旋转缩放两个view了。

9、tap点击手势

这里为了方便看到tap的效果,当点击一下屏幕时,播放一个声音。

为了播放声音,我们加入avfoundation.framework这个框架。

?

1

2

3

4

5

6

7

8

9

10

11
- (avaudioplayer *)loadwav:(nsstring *)filename {

nsurl * url = [[nsbundle mainbundle] urlforresource:filename withextension:@"wav"];

nserror * error;

avaudioplayer * player = [[avaudioplayer alloc] initwithcontentsofurl:url error:&error];

if (!player) {

nslog(@"error loading %@: %@", url, error.localizeddescription);

} else {

[player preparetoplay];

}

return player;

}

我会在最后例子代码给出完整代码,添加手势的步骤和前面一样的。

?

1

2

3

4

5

6

7

8

9

10

11
#import <uikit/uikit.h>

#import <avfoundation/avfoundation.h>

@interface viewcontroller : uiviewcontroller<uigesturerecognizerdelegate>

@property (strong) avaudioplayer * chompplayer;

@property (strong) avaudioplayer * heheplayer;

@end

- (void)handletap:(uitapgesturerecognizer *)recognizer {

[self.chompplayer play];

}

运行,点一下某个图,就会播放一个咬东西的声音。

不过这个点击播放声音有点缺陷,就是在慢慢拖动的时候也会播放。这使得两个手势重合了。怎么解决呢?使用手势的:

requiregesturerecognizertofail方法。

10、手势的依赖性

在viewdidload的循环里添加这段代码:

?

1
[taprecognizer requiregesturerecognizertofail:pangesturerecognizer];

意思就是,当如果pan手势失败,就是没发生拖动,才会出发tap手势。这样如果你有轻微的拖动,那就是pan手势发生了。tap的声音就不会发出来了。

11、自定义手势

自定义手势继承:uigesturerecognizer,实现下面的方法:

?

1

2

3

4
– touchesbegan:withevent:

– touchesmoved:withevent:

– touchesended:withevent:

- touchescancelled:withevent:

新建一个类,继承uigesturerecognizer,代码如下:
.h文件

?

1

2

3

4

5

6

7

8

9

10

11

12

13
#import <uikit/uikit.h>

typedef enum {

directionunknown = 0,

directionleft,

directionright

} direction;

@interface happygesturerecognizer : uigesturerecognizer

@property (assign) int ticklecount;

@property (assign) cgpoint curticklestart;

@property (assign) direction lastdirection;

@end

.m文件

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65
#import "happygesturerecognizer.h"

#import <uikit/uigesturerecognizersubclass.h>

#define required_tickles 2

#define move_amt_per_tickle 25

@implementation happygesturerecognizer

- (void)touchesbegan:(nsset *)touches withevent:(uievent *)event {

uitouch * touch = [touches anyobject];

self.curticklestart = [touch locationinview:self.view];

}

- (void)touchesmoved:(nsset *)touches withevent:(uievent *)event {

// make sure we've moved a minimum amount since curticklestart

uitouch * touch = [touches anyobject];

cgpoint ticklepoint = [touch locationinview:self.view];

cgfloat moveamt = ticklepoint.x - self.curticklestart.x;

direction curdirection;

if (moveamt < 0) {

curdirection = directionleft;

} else {

curdirection = directionright;

}

if (abs(moveamt) < move_amt_per_tickle) return;

// 确认方向改变了

if (self.lastdirection == directionunknown ||

(self.lastdirection == directionleft && curdirection == directionright) ||

(self.lastdirection == directionright && curdirection == directionleft)) {

// 挠痒次数

self.ticklecount++;

self.curticklestart = ticklepoint;

self.lastdirection = curdirection;

// 一旦挠痒次数超过指定数,设置手势为结束状态

// 这样回调函数会被调用。

if (self.state == uigesturerecognizerstatepossible && self.ticklecount > required_tickles) {

[self setstate:uigesturerecognizerstateended];

}

}

}

- (void)reset {

self.ticklecount = 0;

self.curticklestart = cgpointzero;

self.lastdirection = directionunknown;

if (self.state == uigesturerecognizerstatepossible) {

[self setstate:uigesturerecognizerstatefailed];

}

}

- (void)touchesended:(nsset *)touches withevent:(uievent *)event

{

[self reset];

}

- (void)touchescancelled:(nsset *)touches withevent:(uievent *)event

{

[self reset];

}

@end

调用自定义手势和上面一样,回到这样写:

?

1

2

3
- (void)handlehappy:(happygesturerecognizer *)recognizer{

[self.heheplayer play];

}

手势成功后播放呵呵笑的声音。

在真机上运行,按住某个view,快速左右拖动,就会发出笑的声音了。

代码解析:

先获取起始坐标:curticklestart

通过和ticklepoint的x值对比,得出当前的放下是向左还是向右。再算出移动的x的值是否比move_amt_per_tickle距离大,如果太则返回。

再判断是否有三次是不同方向的动作,如果是则手势结束,回调。

源代码:源代码下载。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS手势识别的详细使用方法(拖动,缩放,旋转,点击,手势依赖,自定义手势) https://www.kuaiidc.com/91382.html

相关文章

发表评论
暂无评论