手势是指用一个或多个手指接触屏幕时开始,知道手指离开屏幕为止所发生的所有事件. Cocoa Touch没有公开任何代表手势的类或结构,手势就是一个动作,运行中的应用可以从用户输入流知道是否出现某种手势.手势通过一系列事件在系统内传递信息.用户在与设备的多点触控屏幕交互时会触发一系列事件.
触摸:指把手指放到iOS设备的屏幕上,从屏幕上拖动或抬起的这样一种行为,手势中涉及的触摸数量等于同时位于屏幕上的手指数量.(注:iPad可以处理同时发生的11处触摸)
轻点:当用一个手指触摸屏幕,然后立即将该手指从屏幕移开(而不是来回移动).iOS能跟踪轻点的数量,并且可以区分用户究竟是轻点了2次还3次,甚至20次.也能区分是两次单击还是一次双击
手势识别器是一个对象,它知道如何观察用户生成的事件流,并能够识别用户何时以与已定义的手势相匹配的方式进行了触摸和拖动.UIGestureRecognizer
响应者链--转发事件
4个手势通知方法
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
self.gestureStartPoint = [touch locationInView:self];
//轻点次数
NSUInteger numTaps = [[touches anyObject] tapCount];
//触摸个数(几个手指进行触摸)
NSUInteger numTouches = [touches count];
//获取位于特殊视图的触摸的touches
NSSet *myTouches = [event touchesForView:self];
//将点转换为视图的本地坐标系
// CGPoint point = [[touches anyObject] loactionInView:self];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
self.currentPoint = [touch locationInView:self];
}
//当发生某些事件(如来电呼叫)导致手势中断,该方法会被调用,可以在此处进行清理工作,以便重新开始一个新手势,该方法被调用时,对于当前手势,不会调用touchesEnded:withEvent:
-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
注意:确保View选中User Interacting Enabled 和 Multiple Touch
swipes应用
它只能检测水平和垂直清扫这两种手势.
当用户触摸屏幕时,第一次触摸的位置将被保存在变量中.然后,当用户手指滑过屏幕时,我们将进行检测,看它是否达到某个点以及这个点是否足够远且足够直,以至于能将其算作清扫.
static CGFloat const kMinimumGestureLength = 25;
static CGFloat const kMaximumVariance = 5;
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
self.gestureStartPoint = [touch locationInView:self.view];
}
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
CGFloat deltaX = fabs(self.gestureStartPoint.x - currentPoint.x);
CGFloat deltaY = fabs(self.gestureStartPoint.y - currentPoint.y);
if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) {
NSLog(@"Horizontal swipe detected");
[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}else if (deltaY >= kMinimumGestureLength && deltaX<= kMaximumVariance){
NSLog(@"Vertical swipe detected");
[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}
}
自动手势识别
iOS现在包含一个名为UIGestureRecognizer的类,创建它的一个子类的实例,其中每个子类用于查找特定类型的手势,比如轻扫,捏合,双击,三击等
- (void)viewDidLoad {
[super viewDidLoad];
UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(reportVerticalSwipe:)];
vertical.direction = UISwipeGestureRecognizerDirectionUp|UISwipeGestureRecognizerDirectionDown;
[self.view addGestureRecognizer:vertical];
UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(reportHorizontalSwipe:)];
horizontal.direction = UISwipeGestureRecognizerDirectionRight|UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:horizontal];
}
-(void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer
{
NSLog(@"Vertical swipe detected");
[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
//recongnizer.numberOfTouches 为触摸时的手指个数
}
-(void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer
{
NSLog(@"Horizontal swipe detected");
[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}
多指轻扫
- (void)viewDidLoad {
[super viewDidLoad];
for (NSUInteger touchCount = 1; touchCount <= 5 ; touchCount ++) {
UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(reportVerticalSwipe:)];
vertical.direction = UISwipeGestureRecognizerDirectionUp|UISwipeGestureRecognizerDirectionDown;
vertical.numberOfTouchesRequired = touchCount;
[self.view addGestureRecognizer:vertical];
UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(reportHorizontalSwipe:)];
horizontal.direction = UISwipeGestureRecognizerDirectionRight|UISwipeGestureRecognizerDirectionLeft;
horizontal.numberOfTouchesRequired = touchCount;
[self.view addGestureRecognizer:horizontal];
}
}
-(NSString *)descriptionForTouchCount:(NSUInteger)touchCount
{
switch (touchCount) {
case 1:
return @"Single";
break;
case 2:
return @"Double";
break;
case 3:
return @"Triple";
break;
case 4:
return @"Quadruple";
break;
case 5:
return @"Quintuple";
break;
default:
return @"0";
break;
}
}
-(void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer
{
NSLog(@"%@ Vertical swipe detected",[self descriptionForTouchCount:recognizer.numberOfTouches]);
[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}
-(void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer
{
NSLog(@"%@ Horizontal swipe detected",[self descriptionForTouchCount:recognizer.numberOfTouches]);
[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];
}
检测多次轻点
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *sigleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleTap:)];
sigleTap.numberOfTapsRequired = 1;
sigleTap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:sigleTap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTap:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:doubleTap];
UITapGestureRecognizer *tripleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tripleTap:)];
tripleTap.numberOfTapsRequired = 3;
tripleTap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:tripleTap];
[sigleTap requireGestureRecognizerToFail:doubleTap];
[sigleTap requireGestureRecognizerToFail:tripleTap];
[doubleTap requireGestureRecognizerToFail:tripleTap];
}
-(void)singleTap:(UIGestureRecognizer *)recognizer
{
NSLog(@"sigle tap detacted");
}
-(void)doubleTap:(UIGestureRecognizer *)recognizer
{
NSLog(@"double tap detacted");
}
-(void)tripleTap:(UIGestureRecognizer *)recognizer
{
NSLog(@"triple tap detacted");
}
检测捏合和旋转
双指捏合:UIPinchGestureRecognizer.此识别器称为连续手势识别器,因为它在双指捏合期间反复调用自己的操作方法,双指捏合手势识别器经历多个状态,我们唯一希望观察的是UIGestureRecognizerStateBegan,识别器的scale属性此时为1,对于手势的其他状态,该数值将随着用户手指相对于其实位置的移动上升或下降,我们将使用scale值调整标签中文本的大小.
双指旋转:UIRotationGestureRecognizer--连续的手势识别器.有个rotation属性,开始默认是0.0.在旋转过程中这个值可在0.0到2.0*PI之间变化
@interface ViewController ()
@property(strong,nonatomic)UIImageView *imageView;
@end
@implementation ViewController
{
CGFloat scale,previousScale;
CGFloat rotation,previousRotation;
}
- (void)viewDidLoad {
[super viewDidLoad];
previousScale = 1.0;
UIImage *image = [UIImage imageNamed:@"construction-big"];
self.imageView = [[UIImageView alloc]initWithImage:image];
self.imageView.userInteractionEnabled = YES;//imageView默认是关闭交互的
self.imageView.center = self.view.center;
[self.view addSubview:self.imageView];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(doPinch:)];
pinchGesture.delegate = self ;
[self.imageView addGestureRecognizer:pinchGesture];
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(doRotate:)];
rotationGesture.delegate = self;
[self.imageView addGestureRecognizer:rotationGesture];
}
-(void)transformImageView
{
CGAffineTransform t = CGAffineTransformMakeScale(scale*previousScale, scale*previousScale);
t = CGAffineTransformRotate(t, rotation+previousRotation);
self.imageView.transform = t;
}
-(void)doPinch:(UIPinchGestureRecognizer *)recognizer
{
scale = recognizer.scale;
[self transformImageView];
if (recognizer.state == UIGestureRecognizerStateEnded) {
previousScale = scale *previousScale;
scale = 1;
}
}
-(void)doRotate:(UIRotationGestureRecognizer *)recognizer
{
rotation = recognizer.rotation;
[self transformImageView];
if (recognizer.state == UIGestureRecognizerStateEnded) {
previousRotation = rotation + previousRotation ;
rotation = 0;
}
}
#pragma mark -- UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}