手势识别器(Gesture Recognizer)用于识别触摸序列并触发响应事件。当手势识别器识别到一个手势或手势发生变化时,会触发响应事件。UIGestureRecognizer类作为抽象类,不能直接使用。只能使用UIGestureRecognizer的子类识别手势,每一个子类识别一个特定的手势。UIGestureRecognizer有以下几个子类:

  1. UITapGestureRecognizer:点击手势识别器,手势可以是一次点击或多次点击,可以是一个手指也可以是多个手指。点击手势是最为常用的手势。
  2. UISwipeGestureRecognizer:滑动手势识别器,滑动方向可以是上下左右任一方向。滑动手势的典型示例是查看照片的应用程序,我们使用手指从一张照片滑动到另一张照片。
  3. UIPanGestureRecognizer:平移手势识别器,也称为拖动手势识别器。当用户平移视图时,必须保持一个或多个手指始终按压在视图上。
  4. UIPinchGestureRecognizer:捏合手势识别器,需要两个手指同时触摸视图。当两个手指靠近时,视图缩小;当两根手指远离时,视图放大。
  5. UIRotationGestureRecognizer:旋转手势识别器,需要两个手指同时触摸视图。当用户手指彼此相对做圆周运动时,对应视图会以相同的方向和速度旋转。
  6. UILongPressGestureRecognizer:长按手势识别器,想要成功触发长按手势,需使用一个或多个手指在视图上按压不小于minimumPressDuration设定的时长,默认0.5秒,并且长按时手指移动的距离要小于allowableMovement设定的距离,默认距离10points。
  7. UIScreenEdgePanGestureRecognizer:屏幕边缘轻扫手势识别器,继承自UIPanGestureRecognizer,前面六个手势识别器均继承自UIGestureRecognizer。屏幕边缘轻扫手势识别器只能识别在屏幕边缘附近开始的手势。与滑动手势很像,不同之处在于前者必须从屏幕边缘开始。可以使用屏幕边缘手势来启动视图控制器转换。

上面的这些手势不是离散(discrete)的就是连续(continuous)的。离散的手势识别器从手势开始到结束只向目标发送单个动作消息,例如点击手势、滑动手势。连续手势的手势识别器为每个增量变化发送动作消息,直到多点触摸序列结束,例如平移手势、捏合手势、旋转手势。

窗口在将触摸事件递送给视图前会先递送给手势识别器。如果手势识别器不能识别出该触摸事件,窗口才会把触摸事件递送给添加手势识别器的视图;如果手势识别器可以识别出该触摸事件,对应视图将不会收到窗口递送的触摸事件。

一旦检测到有效的手势,手势识别器会触发响应事件。当调用响应方法时,一般会把手势识别器作为参数,以便在处理手势事件需要额外信息时可供使用。把手势识别器作为参数不是必须的,但会是一个良好的编程习惯。

- (void)handleTapGesture;
- (void)handleTapGestureWithGestureRecognizer:(UITapGestureRecognizer *)gestureRecognizer;

在上面的代码中,如果你需要获取手势在视图控制器中的位置,可以通过参数gestureRecognizer调用locationInView:方法获取。所以在本教程示例中,所有手势响应方法都会带有参数。

一个手势识别器只能添加到一个视图,一个视图可以添加多个手势识别器。例如,可以为图片视图添加捏合手势和旋转手势,这样你就可以放大、缩小或旋转图片。然而,手势识别器一次只能识别一个手势,它不能把你的手势同时识别为捏合手势和旋转手势。添加到同一视图上的手势识别器都会被添加到该视图的数组中,可以像使用其它数组一样使用该数组,但很少需要这样做。

手势识别器即可以通过界面构建器(Interface Builder)添加,也可以通过代码添加。在这篇文章,我们将使用代码添加。

创建demo

这篇文章主要讲解1至5五个手势识别器,6和7两个识别器只做简单介绍。

首先我们会创建Tabbed Application模板的应用,设置应用包含五个tab,每一个tab对应一个单独视图控制器,每一个视图控制器对应一个手势识别器。我们讲解手势识别器的顺序与上面介绍顺序相同,在讲解每一个手势识别器时会添加一个或多个UIView,并在对应的视图控制器中添加代码,所以这一个demo会被划分为5个小的示例。

启动Xcode,点击File > New > File…,选择iOS > Application > Tabbed Application模板,点击Next;在Product Name中填写GesturesDemo,点击Next;选择文件位置,点击Create创建工程。

现在设置用户界面以便稍后可以直接使用手势识别器。点击Main.storyboard,可以看到系统自动创建了两个连接到选项卡栏控制器的视图控制器,所以还需要手动添加三个视图控制器。从对象库(Object Library)中拖拽三个视图控制器到界面构建器画布中。

在将视图控制器连接到选项卡栏之前,必须创建必要的视图控制器。首先选中FirstViewControllerSecondViewController类文件(包括.h和.m文件)并删除,在Xcode菜单栏中点击File > New > File… ,从弹出的窗口中选择iOS > Application > Cocoa Touch Class,点击Next;在弹出窗口的Class文本框内填写TapViewController,父类为UIViewController,点击Next;选择文件位置,点击Create创建文件。

重复上面添加TapViewController的方法,依次创建名称如下的视图控制器。

  • SwipeViewController
  • PanViewController
  • PinchViewController
  • RotationViewController

操作完成后,你的项目导航器(Project Navigator)应该和下图一样。

回到界面构建器,打开右上角Utilities,选中第一个视图控制器,打开Utilities中的Identify Inspector,把Custom Class中的Class设置为我们的第一个视图控制器名称TapViewController

重复以上步骤,为其余四个视图控制器添加自定义类。

下面把所有的视图控制器连接到选项卡栏控制器。首先选中选项卡栏控制器,其次打开Utilities中的Connections Inspector,在Triggered Segues一栏内,点击view controllers右侧的圆并拖拽到没有连接到选项卡栏控制器的控制器。重复此步骤,直到所有视图控制器均连接到选项卡栏控制器。

现在,设置视图控制器在选项卡栏的标题。选中选项卡栏,打开Utilities中的Attributes Inspector,为每一个视图控制器设置对应的选项卡标题,所有的视图控制器的image都设置为first

选项卡栏标题依次为:

  • Tap
  • Swipe
  • Pan
  • Pinch
  • Rotation

最后删除系统自动创建的两个视图控制器上的UILabel。现在为每一个视图控制器添加一个UILabel用以显示视图控制器的名称。这里使用的是Xcode 8.2.1,模拟器为iphone 7 plus,iOS 10.2,UILabel属性如下,如果你是其他版本,frame属性可能不同。

  • Frame: X=20,Y=57,Width=374,Height=24
  • Font:System Bold,20pt
  • Alignment:Center

和上面的顺序一样,均是自上而下。标签的内容依次为:

  • Tap Gesture
  • Swipe Gesture
  • Pan Gesture
  • Pinch Gesture
  • Rotation Gesture

1. 点击手势识别器UITapGestureRecognizer

现在给TapViewController添加一个UIView用以学习UITapGestureRecognizer,打开Main.storyboard,选中TapViewController,从对象库中拖拽一个UIViewTapViewControllerUIView属性如下:

  • Frame: x=132, y=293, Width=150, Height=150
  • Background Color: orange

打开Xcode中右上角的Assistant editor,从左侧的TapViewControllerUILabel中拖拽IBOutlet到右侧TapViewController.m的头文件中,在弹出窗口中Name文本框内填写testView

在后面我们会多次用到上面的方法为UIView创建IBOutlet属性,但不再详细描述过程。

进入TapViewController.m,在viewDidLoad方法中,我们初始化一个手势识别器,并把它添加到testView中。

- (void)viewDidLoad
{[super viewDidLoad];// 1.1 初始化手势识别器UITapGestureRecognizer *singleGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];// 1.2 添加手势识别器[self.testView addGestureRecognizer:singleGestureRecognizer];
}

使用1.1的方法初始化点击手势识别器,initWithTarget:的参数一般是self,即指定当前视图控制器接收手势识别器发送的消息。action:为手势所触发的操作。点击手势识别器默认是一次点击、一个手指点击。使用1.2的方法添加点击手势识别器到testViewaddGestureRecognizer:方法是向视图添加手势识别器的标准方法。

TapViewController.m中实现手势中的handleSingleTapGesture:方法,在第一次单击testView时,把它的宽放大2倍;第二次点击时,恢复为原来大小。

- (void)handleSingleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer
{NSLog(@"Single Tap");CGFloat newWidth = 150;if (self.testView.frame.size.width == 150){newWidth = 300;}CGPoint currentCenter = self.testView.center;self.testView.frame = CGRectMake(self.testView.frame.origin.x, self.testView.frame.origin.y, newWidth, self.testView.frame.size.height);self.testView.center = currentCenter;
}

现在运行app,点击Tap Gesture中的testView。第一次点击时,testView宽度变为原来二倍,再次点击,恢复为原来大小。

现在为testView添加一个双击手势,更新后如下:

- (void)viewDidLoad
{...// 2.1 初始化双击手势UITapGestureRecognizer *doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTapGesture:)];// 2.2 需要两次点击doubleTapGestureRecognizer.numberOfTapsRequired = 2;// 2.3 添加手势识别器[self.testView addGestureRecognizer:doubleTapGestureRecognizer];// 3 单机手势遇到双击手势时只响应双击手势[singleGestureRecognizer requireGestureRecognizerToFail:doubleTapGestureRecognizer];
}

在上面的代码中,在2.1中初始化一个点击手势,并指定点击手势发生时的动作方法;在2.2中利用numberOfTapsRequired属性设定需要点击两次才能触发双击手势;在2.3中,把手势识别器添加到testView。现在,testView包含两个手势识别器,双击时会被识别为先单机后双击,所以在3中设置当单机手势遇到双击手势时,只响应双击手势。

现在我们实现双击手势中的handleDoubleTapGesture:方法。第一次双击时,testView长、宽均变为原来二倍,第二次双击时,恢复原来大小。

- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer
{NSLog(@"Double Tap");CGSize newSize = CGSizeMake(150, 150);if (self.testView.frame.size.width == 150){newSize.width = 300;newSize.height = 300;}CGPoint currentCenter = self.testView.center;self.testView.frame = CGRectMake(self.testView.frame.origin.x, self.testView.frame.origin.y, newSize.width, newSize.height);self.testView.center = currentCenter;
}

现在运行app,使用一根手指连续两次点击testView,可以看到testView长宽变为原来二倍,再次双击变为原来大小。最后单机testView,和之前一样宽度变为原来二倍。

2. 滑动手势识别器UISwipeGestureRecognizer

滑动手势可以滑向上下左右的任一方向,但不包括对角线方向,使用UISwipeGestureRecognizerDirection类提供的dircetion属性指定手势的滑动方向,如果没有设置滑动方向,默认向右侧滑动。每一个手势识别器只能识别一个滑动方向,所以如果需要识别多个方向,需要添加多个手势识别器。另外,滑动手势识别器的动作方法在滑动手势结束那一刻被调用。

滑动手势可快可慢。慢的滑动需要高精度方向,但所需动距离短些;快速滑动需要低精度的方向,但所需滑动距离长些。

在这一部分,使用之前创建的SwipeViewController学习滑动手势。在SwipeViewController中添加三个UIView,每一个视图的宽度等于当前窗口的宽度。第一个视图在视图控制器的中部,第二个和第三个分别放在第一个的左右两侧,第二个和第三个视图我们将不能在视图中看到。我们这里的目标就是把三个视图水平放置,通过滑动手势让隐藏的视图显示。

打开Main.storyboard,选中Swipe Scene,拖拽三个UIViewSwipeViewController,设置UIView的属性如下。

First View
  • Frame:x=0, y=304, Width=414, Height=128
  • Background Color: orange
Second View
  • Frame: x=-414, y=304, Width=414, Height=128
  • Background Color: red
Third View
  • Frame:x=414, y=304, Width=414, Height=128
  • Background Color: black

为刚添加的UIViewSwipeViewController.m中添加IBOutlet属性。

#import "SwipeViewController.h"@interface SwipeViewController ()@property (strong, nonatomic) IBOutlet UIView *viewOrange;
@property (strong, nonatomic) IBOutlet UIView *viewBlack;
@property (strong, nonatomic) IBOutlet UIView *viewRed;@end

进入viewDidLoad方法,初始化两个滑动手势识别器,分别对应右滑、左滑,最后添加到中间的viewOrange中。

- (void)viewDidLoad
{[super viewDidLoad];// 初始化滑动手势识别器 滑动方向为右滑 添加到viewOrangeUISwipeGestureRecognizer *swipeRightOrange = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(slideToRightWithGestureRecognizer:)];swipeRightOrange.direction = UISwipeGestureRecognizerDirectionRight;[self.viewOrange addGestureRecognizer:swipeRightOrange];// 初始化滑动手势识别器 滑动方向为左滑 添加到viewOrangeUISwipeGestureRecognizer *swipeLeftOrange = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(slideToLeftWithGestureRecognizer:)];swipeLeftOrange.direction = UISwipeGestureRecognizerDirectionLeft;[self.viewOrange addGestureRecognizer:swipeLeftOrange];
}

当我们滑动中间viewOrange视图时,整个视图包括viewBlackviewRed都会一起滑动,所以当一个视图离开视野时,另一个视图出现。下面我们实现右滑手势发生时的动作方法。

- (void)slideToRightWithGestureRecognizer:(UISwipeGestureRecognizer *)swipeGestureRecognizer
{NSLog(@"Swipe Right");CGFloat viewWidth = self.view.frame.size.width;// 右移[UIView animateWithDuration:0.5 animations:^{self.viewOrange.frame = CGRectOffset(self.viewOrange.frame, viewWidth, 0);self.viewBlack.frame = CGRectOffset(self.viewBlack.frame, viewWidth, 0);self.viewRed.frame = CGRectOffset(self.viewRed.frame, viewWidth, 0);}];
}

当我们右滑时,我们希望每个视图右移的距离和当前窗口的宽度一致,使用animateWithDuration: animations:方法移动视图会让整个过程变得美观,这里动画移动的快慢取决于动画持续的时间,持续时间越长,动画越慢。

下面实现左滑发生时的动作方法。与实现的右滑动作方法类似,只是这次是左滑,x需要左移。

- (void)slideToLeftWithGestureRecognizer:(UISwipeGestureRecognizer *)swipeGestureRecognizer
{NSLog(@"Swipe Left");CGFloat viewWidth = self.view.frame.size.width;// 左移[UIView animateWithDuration:0.5 animations:^{self.viewOrange.frame = CGRectOffset(self.viewOrange.frame, -viewWidth, 0);self.viewBlack.frame = CGRectOffset(self.viewBlack.frame, -viewWidth, 0);self.viewRed.frame = CGRectOffset(self.viewRed.frame, -viewWidth, 0);}];
}

现在运行app,进入Swipe选项卡,左滑或右滑,视图会以动画形式移动,但是移动一次后不能再次滑动。因为我们的手势只添加到了中间的viewOrange,下面为处于左侧的viewRed添加左滑手势识别器,处于右侧的viewBlack添加右滑手势识别器。因为三个视图左滑和右滑所需移动的视图一致,所以只需要调用相同方法即可。

- (void)viewDidLoad
{...// viewRed添加左滑手势识别器UISwipeGestureRecognizer *swipeLeftRed = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(slideToLeftWithGestureRecognizer:)];swipeLeftRed.direction = UISwipeGestureRecognizerDirectionLeft;[self.viewRed addGestureRecognizer:swipeLeftRed];// viewBlack添加右滑手势识别器UISwipeGestureRecognizer *swipeRightBlack = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(slideToRightWithGestureRecognizer:)];swipeRightBlack.direction = UISwipeGestureRecognizerDirectionRight;[self.viewBlack addGestureRecognizer:swipeRightBlack];
}

现在运行app,一切正常。

因为视图中添加手势识别器发生在runtime,而非compile time,所以每一个手势识别器只能添加到一个视图。如果只创建一个手势识别器,添加到多个视图,手势识别器将不能正常工作。如果你想验证,你可以把swipeRightOrangeswipeLeftOrange添加到另外两个视图,同时注销另外两个视图之前的手势识别器,运行app,像之前一样滑动视图,你会发现手势无法正常识别。

3. 平移手势识别器UIPanGestureRecognizer

在这一部分学习平移手势识别器(UIPanGestureRecognizer),或称为拖动手势识别器。这个手势可以使用户按压住视图在窗口内随意拖动,在用户拖动的过程中,必须保持手指一直按压在视图上。使用UIPanGestureRecognizer类的velocityInView:方法可以获取拖动手势移动的速度。

和以往一样,打开Main.storyboard,选中Pan Scene,从对象库拖拽一个UIView添加到PanViewController,设置其属性如下:

  • Frame: x=132, y=293, Width=150, Height=150
  • Background Color: orange

为刚添加的UIViewPanViewController.m中创建IBOutlet属性。

#import "PanViewController.h"@interface PanViewController ()@property (strong, nonatomic) IBOutlet UIView *testView;@end

下面在viewDidLoad方法中初始化UIPanGestureRecognizer,并添加到testView

- (void)viewDidLoad
{[super viewDidLoad];UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveViewWithGestureRecognizer:)];[self.testView addGestureRecognizer:panGestureRecognizer];
}

我们想要实现的是当手指按住视图后,视图随手指在屏幕上移动,最简单的方法是让视图的中心随手势移动。下面实现moveViewWithGestureRecognizer:方法。

- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer
{NSLog(@"Pan Tap");CGPoint touchPoint = [panGestureRecognizer locationInView:self.view];self.testView.center = touchPoint;
}

任何类型的手势识别器都可以使用locationInview:方法。这个方法返回用户触摸点的CGPoint值。在这个示例中,通过此方法获取拖动过程中手势所在的点,通过把该点设为testView的中心来达到拖动效果。另外,在上面代码中可以直接接触到响应手势的视图,但有时可能无法接触到,前面也提到响应方法中的参数可以提供额外信息,所以我们提供一种更为通用的方式,

- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer
{...
//    self.testView.center = touchPoint;panGestureRecognizer.view.center = touchPoint;
}

第一部分的UITapGestureRecognizer也可以用此方法,你可以自己尝试修改,如果遇到问题,可以通过文章底部的连接下载这个demo的完整代码查看。

在这一部分的开始,说到可以使用velocityInView:方法获取拖动的速度,现在来实现它。

首先,进入Main.stroyboard,选中Pan Scene,为PanViewController添加两个UILabel,设置其属性如下:

Label #1
  • Frame: x=20, y=582, Width=374, Height=21
  • Text: Horizontal Velocity
Label #2
  • Frame: x=20, y=628, Width=374, Height = 21
  • Text: Vertical Velocity

稍后将使用这两个标签显示x轴和y轴的速度。在此之前,先为添加的两个UILabel创建IBOutlet属性。

#import "PanViewController.h"@interface PanViewController ()...
@property (strong, nonatomic) IBOutlet UILabel *horizontalVelocityLabel;
@property (strong, nonatomic) IBOutlet UILabel *verticalVelocityLabel;@end

进入PanViewController.m,在moveViewWithGestureRecognizer:方法中添加一些代码,以便我们能够获得拖动的速度,该速度是一个CGPoint类型的值,单位是points每秒,然后我们提取每个轴上的速度并显示到对应的UILabel上。

- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer
{...// 获取移动速度并显示到标签CGPoint velocity = [panGestureRecognizer velocityInView:self.view];self.horizontalVelocityLabel.text = [NSString stringWithFormat:@"Horizontal Velocity: %.2f points/sec",velocity.x]; // x轴速度self.verticalVelocityLabel.text = [NSString stringWithFormat:@"Vertical Velocity: %.2f points/sec",velocity.y]; // y轴速度
}

现在运行app,拖动视图,你可以看到移动的速度。

4. 捏合手势识别器UIPinchGestureRecognizer

捏合手势识别器(UIPinchGestureRecognizer)当用户两个手指靠近时缩小视图,两个手指远离时放大视图,最常见的就是浏览照片时对照片捏合缩放,但在这一部分没有使用UIImageView,而是在UIView上添加UIPinchGestureRecognizer,捏合手势识别器必须两个手指同时操作,这一点与前面几个示例不同。

与前面几个示例相同,首先在Pinch Scene上添加UIView,其属性如下:

  • Frame: x=107, y=268, Width=200, Height=200
  • Background Color: orange

为刚添加的UIViewPinchViewController.m中添加IBOutlet属性。

#import "PinchViewController.h"@interface PinchViewController ()@property (strong, nonatomic) IBOutlet UIView *testView;@end

进入PinchViewController.m,在viewDidLoad方法中初始化捏合手势识别器,并添加到testView

- (void)viewDidLoad
{[super viewDidLoad];UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchWithGestureRecognizer:)];[self.testView addGestureRecognizer:pinchGestureRecognizer];
}

在动作方法中,通过改变scale来改变testView的变换(transform),这样会产生放大或缩小效果。

- (void)handlePinchWithGestureRecognizer:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{NSLog(@"Pinch Gesture");pinchGestureRecognizer.view.transform = CGAffineTransformScale(pinchGestureRecognizer.view.transform, pinchGestureRecognizer.scale, pinchGestureRecognizer.scale);pinchGestureRecognizer.scale = 1.0;     // 重设scale
}

现在运行app,测试捏合手势。在模拟器中可以使用option和鼠标左键模拟两个手指触摸屏幕。

5. 旋转手势识别器UIRotationGestureRecognizer

旋转手势识别器(UIRotationGestureRecognizer)与捏合手势类似,都需要两个手指,通过修改rotation来改变视图的变换。通常,旋转手势与其他手势组合使用。

打开Main.storyboard,选中Rotation Scene,从对象库中拖拽一个UIViewRotationViewController,并设置其属性如下:

  • Frame: x=132, y=293, Width=150, Height=150
  • Background Color: orange

为刚添加的UIViewRotationViewController.m中创建IBOutlet属性。

#import "RotationViewController.h"@interface RotationViewController ()@property (strong, nonatomic) IBOutlet UIView *testView;@end

进入RotationViewController.m,在viewDidLoad方法中初始化旋转手势识别器,并添加到testView

- (void)viewDidLoad {[super viewDidLoad];UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotationWithGestureRecognizer:)];[self.testView addGestureRecognizer:rotationGestureRecognizer];
}

下面实现动作方法。通过使用CGAffineTransformRotate方法改变testView转换(transform)的旋转值(rotation),最后记得设置rotation属性的初始值。

- (void)handleRotationWithGestureRecognizer:(UIRotationGestureRecognizer *)rotationGestureRecognizer
{NSLog(@"Rotation Gesture");rotationGestureRecognizer.view.transform = CGAffineTransformRotate(rotationGestureRecognizer.view.transform, rotationGestureRecognizer.rotation);rotationGestureRecognizer.rotation = 0.0;
}

运行app,在Rotation Gesture界面,用两指以任意时针方向旋转testView

6. 长按手势识别器UILongPressGestureRecognizer和屏幕边缘轻扫手势识别器UIScreenEdgePanGestureRecognizer

长按手势识别器(UILongPressGestureRecognizer)和屏幕边缘轻扫手势识别器(UIScreenEdgePanGestureRecognizer)只做简单介绍,不在使用代码详细说明。

使用长按手势时用户必须使用一个或多个手指,按压视图一定时间才能触发响应。UILongPressGestureRecognizer类包含以下四个属性:

  • minimumPressDuration:触发长按手势所需按压的最短时间,单位是秒,默认为0.5秒。
  • numberOfTouchesRequired:触发长按手势所需手指数,默认为1。
  • numberOfTapsRequired:触发长按手势所需点击数,默认为0。
  • allowableMovement:手指按压住视图后允许手指移动的最大距离,单位point,默认10 points。

使用长按手势识别器时记得设置上面这些属性。另外,长按手势也是连续的。

屏幕边缘轻扫手势识别器(UIScreenEdgePanGestureRecognizer)和滑动手势识别器很像,不同之处在于屏幕边缘轻扫手势必须从屏幕边缘开始。在Safari浏览器上,从屏幕左边缘滑动,可以回到上一页面,导航控制器默认支持这一功能。使用这一功能时,需要使用edges属性指定手势开始的边缘,你所指定的边缘应当对应于当前应用程序界面方向,这样才能确保手势始终从用户界面相同位置发生,而不受设备当前方向影响。

你可能发现每一个手势的响应方法中都添加了NSLog方法,这样可以在动作方法执行时在控制台看到输出。你可以再运行一次app,测试每一个手势,你会发现UITapGestureRecognizerUISwipeGestureRecognizerUIPanGestureRecognizer三个手势识别器一个手势执行一次动作方法,它们是离散(discrete)的。UIPinchGestureRecognizerUIRotationGestureRecognizer会多次调用动作方法,它们是连续(continuous)的。

看完这篇文章,你会发现UIGestureRecoginzer是如此简单。如果需要,可以点击下面连接获取源码。

Demo名称:GestureRecognizer
源码地址:https://github.com/pro648/BasicDemos-iOS

参考资料:

  1. Using Gesture Recognizers to Handle Pinch, Rotate, Pan, Swipe and Tap Gestures
  2. UIGesture​Recognizer
  3. Can you attach a UIGestureRecognizer to multiple views?

欢迎更多指正:https://github.com/pro648/tips/wiki

本文地址:https://github.com/pro648/tips/wiki/手势控制:点击、滑动、平移、捏合、旋转、长按、轻扫

手势控制:点击、滑动、平移、捏合、旋转、长按、轻扫相关推荐

  1. iOS 手势的使用 六个手势 轻拍 长按 拖拽 捏合 轻扫 旋转

    手势识别在iOS上非常重要,手势操作移动设备的重要特征,极大的增加了移动设备使用便捷性. iOS系统在3.2以后,为方便开发这使用一些常用的手势,提供了UIGestureRecognizer类.手势识 ...

  2. Unity实现安卓端手势控制摄像机的旋转和缩放

    说明   上一篇记录了PC端鼠标控制摄像机的移动和缩放,这一篇写的是在安卓机上实现手势控制摄像机围绕一个物体进行旋转和缩放,两篇的代码逻辑基本一样只是输入检测有区别,这里我是分开记录,没有整合[Uni ...

  3. Unity 触屏手势控制Camera平移旋转缩放

    Unity 触屏手势控制Camera平移旋转缩放 实现思路 单点触屏,位移增量控制相机平移: 两点触屏,两点位移控制相机前后移动(缩放):两点中一点不位移控制相机绕点旋转: 实现需要的API Touc ...

  4. 手势控制控件 的缩放,平移和旋转:

    手势控制控件的缩放,平移和旋转: mapView是要移动的控件,TouchLayout是手势控制的区域,具体代码如下: touchLayout.setOnTouchListener(new Touch ...

  5. iOS 手势操作:拖动、捏合、旋转、点按、长按、轻扫、自定义

    http://www.cnblogs.com/huangjianwu/p/4675648.html 1.UIGestureRecognizer 介绍 手势识别在 iOS 中非常重要,他极大地提高了移动 ...

  6. 实际的机械臂控制(9)Moveit单独控制机械臂末端在XYZ三个轴的平移和旋转(基于python)

    0. 序言 在moveit中,控制机械臂的末端执行器运动的API有两个,分别是: shift_pose_target set_pose_target 第一个API:shift_pose_target ...

  7. Unity实现触摸屏手势控制镜头旋转与缩放

    一.关于 Unity实现触摸屏手势控制镜头旋转与缩放脚本 /*** * Title:"三维可视化" 项目 * 主题:手势控制物体的旋转缩放 * Description: * 功能: ...

  8. 手势控制图片旋转(swift)

    做个手势控制图片顺时针.逆时针旋转.主要思路是将图片分为左右半边,手势在左半部分时,往上是顺时针,往下是逆时针,而手势处于右半部分时正好相反,往上逆时针,往下顺时针.在手势回调里代码如下: // MA ...

  9. Unity3D中使用Leap Motion进行手势控制

    Leap Motion作为一款手势识别设备,相比于Kniect,优点在于精确度. 在我的毕业设计<场景漫游器>的开发中,Leap Motion的手势控制作为重要的一个环节.以此,谈谈开发中 ...

最新文章

  1. iOS:自定义模态动画 --UIPresentationController
  2. 【UIKit】UILabel使用
  3. linux内核(4.17.10)配置项详解(x86)
  4. MySQL基于时间字段进行分区的方案总结
  5. python多线程爬虫实例-python 多线程爬虫 实例
  6. 简单web服务器学习总结
  7. Vue删除数据成功后如何刷新表格数据
  8. 电子书下载:The C# Programming Language, 4th Edition
  9. IpIImage - CvMat 转换方法
  10. 前端学习(1883)vue之电商管理系统电商系统之每次只能打开一个菜单项并解决边框问题
  11. 【数据结构与算法】字符串匹配 BF算法 RK算法
  12. #define中 #与##的神奇用法
  13. uni app对接php,thinkphp5 对接手机uni-app的unipush推送(个推)
  14. LED产品认证和检测
  15. 斗鱼password加密参数调试生成案例
  16. 正则表达式lookahead and lookbehind zero-length assertions
  17. 阿里云在线扩容云盘(Windows系统)
  18. ORA-1653: unable to extend table by 1024 in tablespace(oracle表空间满了的解决方案)
  19. 计算机病毒片头制作,怎么用格式工厂做gif_格式工厂怎么制作片头_格式工厂能做什么...
  20. vb整合多个excel表格到一张_如何使用VB实现多个excel表格合并在一个EXCEL表格里面...

热门文章

  1. 如何使用eclipse编写一个简单的java程序
  2. Cypress(赛普拉斯)电容式感应(CapSense)触摸按键应用笔记(工程配置+功能调校+IIC通讯)
  3. 昇陽電腦(SUN公司)
  4. 第十七届 D2 技术大会,前端「聚变」而来!
  5. 090《财务自由之路》简记
  6. DirectSound详细介绍
  7. netsh失败的使用_自用
  8. 体验「UOS」V20 专业版:能代替 Win10 了吗体验
  9. 如何提高蓝牙BLE的传输速率和稳定性
  10. Embedding层