文章目录
- 概要介绍
- UIGestureRecognizer创建方法
- UIGestureRecognizer类常用属性以及方法
- 点击手势
- 使用
- 一定要把视图的用户交互属性设置成YES
- 捏合与旋转
- 使用
- 滑动手势
- 使用
- 拖动手势
- 长按手势
概要介绍
在iphone模拟器上,按住option键这时就能模拟双指触摸了,只能模拟二指水平拖动,旋转效果。
按住option+shift键就能模拟捏合手势。
iOS 一共提供了6种类型的手势操作,分别为:点击,捏合,旋转,滑动,长按,手势需要添加到UIView控件及其子控件之上,同时每个UIView可以添加多个手势。
UIGestureRecognizer类是一个抽象类,不能直接使用。具体使用过程中需要使用其子类,UIGestureRecognizer一共包括6个子类,分别对应6种手势,即:
- UITapGestureRecognizer:点击
- UIPinchGestureRecognizer:捏合
- UIRotationGestureRecognizer:旋转
- UISwipeGestureRecognizer:滑动
- UIPanGesturerecognizer:拖动,其又包含另外一个子类:UIScreenEdgePanGestureRecognizer
- UILongPressGestureRecognizer:长按
UIGestureRecognizer创建方法
- 创建一个UIView类对象
- 创建一个手势类对象,并使用-initWithTarget:action:方法对对象初始化,设置当手势事件发生时,调用的方法。
- 为UIView对象添加手势,使用addGestureRecongnizer方法
- 实现手势事件发生时所调用的方法。
UIGestureRecognizer类常用属性以及方法
UIGestureRecognizer类虽然是一个抽象类,但是其中定义了其子手势类中可以通用的方法和属性。下面的几个方法是需要程序员重点掌握的。
初始化手势对象并设置手势发生时调用的方法
– (instancetype)initWithTarget:(nullable id)target action:(nullable SEL)action;
获取手势点击的位置
– (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(nullable UIView*)view;
获取手势点击的状态和视图
@property(nonatomic,readonly) UIGestureRecognizerState state;
其中:常用的UIGestureRecognizerState有:
UIGestureRecognizerStateBegan:开始手势事件
UIGestureRecognizerStateEnded:结束手势事件
UIGestureRecognizerStateChanged:手势位置发生变化
UIGestureRecognizerStateFailed:无法识别的手势
手势事件对应的视图对象
@property(nullable, nonatomic,readonly) UIView *view;
点击手势
同时能够识别单击以及双击,甚至能够识别到使用几根手指进行点击。
需要点击的次数,用于识别单击或双击,默认为:单击
@property (nonatomic) NSUInteger numberOfTapsRequired;
点击的手指数,默认为:1
@property (nonatomic) NSUInteger numberOfTouchesRequired;
使用
一定要把视图的用户交互属性设置成YES
默认是NO:
self.imageView.userInteractionEnabled=YES;
//
// ViewController.m
// Gesture_base
//
// Copyright © 2019 Shae. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.imageView.userInteractionEnabled=YES;
//单击,单手指
UITapGestureRecognizer *singleTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleTap:)];
//单击
singleTap.numberOfTapsRequired=1;
//单手指
singleTap.numberOfTouchesRequired=1;
//添加到imageView
[self.imageView addGestureRecognizer:singleTap];
//双击,双手指
UITapGestureRecognizer *doubleTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTap:)];
//单击
doubleTap.numberOfTapsRequired=2;
//单手指
doubleTap.numberOfTouchesRequired=2;
//添加到imageView
[self.imageView addGestureRecognizer:doubleTap];
}
-(void)singleTap:(UITapGestureRecognizer*)gesture{
UIAlertController *alertController=[UIAlertController alertControllerWithTitle:@"单击+单手指" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:action];
[self presentViewController:alertController animated:YES completion:nil];
}
-(void)doubleTap:(UITapGestureRecognizer*)gesture{
UIAlertController *alertController=[UIAlertController alertControllerWithTitle:@"双击+双手指" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:action];
[self presentViewController:alertController animated:YES completion:nil];
}
@end
捏合与旋转
捏合手势(UIPinchGestureRecognizer)与旋转手势(UIRotationGestureRecognizer)都可以通过修改UIView对象的transform属性,来实现UI控件的缩放和旋转。
捏合手势可以获取手势在屏幕坐标系中的缩放比例,根据该缩放比例,可以调整UIView控件的缩放。:
@property (nonatomic) CGFloat scale;
旋转手势可以获取手势在屏幕坐标系中的旋转角度,根据该旋转角度,可以调整UIView控件的角度。
@property (nonatomic) CGFloat rotation;
使用
捏合
//捏合手势
UIPinchGestureRecognizer *pinchGesture=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
[self.imageView addGestureRecognizer:pinchGesture];
-(void)pinch:(UIPinchGestureRecognizer*)gesture{
NSLog(@"%f,scale: %f",__func__,gesture.scale);
CGFloat scale=gesture.scale;
self.imageView.transform=CGAffineTransformScale(gesture.view.transform, scale, scale);
//不要使用 CGAffineTransformMake(),会有一些bug
//一定要把scale的值重置为1,否则会影响缩放效果,即缩放比例会在上一次的基础上进行缩小/放大
gesture.scale=1;
}
旋转
//旋转手势
UIRotationGestureRecognizer *rotationGesture=[[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
[self.imageView addGestureRecognizer:rotationGesture];
-(void)rotation:(UIRotationGestureRecognizer*)gesture{
NSLog(@"%s, rotation:%f, velocity:%f",__func__,gesture.rotation,gesture.velocity);
CGFloat rotation=gesture.rotation;
self.imageView.transform=CGAffineTransformRotate(gesture.view.transform, rotation);
//一定要把rotation的值重置为0,否则会影响旋转效果。
gesture.rotation=0;
}
滑动手势
滑动手势(UISwipeGestureRecognizer)常用于照片管理类App,能够实现照片的滑动显示。滑动手指支持向上、向下、向左、向右四个方面的滑动,在创建滑动手势对象时,需要通过direction属性来指定滑动的方向,默认的滑动方向为向右滑动。
@property(nonatomic) UISwipeGestureRecognizerDirection direction;
其中,UISwipeGestureRecognizerDirection的取值包括:
UISwipeGestureRecognizerDirectionRight:向右,默认;
UISwipeGestureRecognizerDirectionLeft:向左;
UISwipeGestureRecognizerDirectionUp:向上;
UISwipeGestureRecognizerDirectionDown:向下。
使用
实现图片管理,左滑和右滑实现图片的切换。
创建一个数组,数组里面存放图片。
@property (nonatomic,strong)NSMutableArray *imageList;
有个索引显示当前显示的图片的索引。
@property(nonatomic,assign)NSInteger imageIndex;
-(NSMutableArray *)imageList{
if (_imageList==nil) {
_imageList=[NSMutableArray array];
for (int i=0; i<4; i++) {
NSString *imageName=[NSString stringWithFormat:@"%d",i];
UIImage *image=[UIImage imageNamed:imageName];
[_imageList addObject:image];
}
}
return _imageList;
}
_imageIndex=0;
//滑动手势默认是向右的
UISwipeGestureRecognizer *swipeRight=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
[self.imageView addGestureRecognizer:swipeRight];
UISwipeGestureRecognizer *swipeLeft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
swipeLeft.direction=UISwipeGestureRecognizerDirectionLeft;
[self.imageView addGestureRecognizer:swipeLeft];
用懒加载的话,都要用self.的方式调用属性。
-(void)swipe:(UISwipeGestureRecognizer*)gesture{
NSInteger imageCount=self.imageList.count;
if (gesture.direction==UISwipeGestureRecognizerDirectionLeft) {
if (_imageIndex>=imageCount-1) return;
self.imageView.image=self.imageList[++_imageIndex];
}else if (gesture.direction==UISwipeGestureRecognizerDirectionRight){
if (_imageIndex<=0) return;
self.imageView.image=self.imageList[--_imageIndex];
}
}
拖动手势
拖动手势(UIPanGestureRecognizer)可以修改一个UI控件的位置,在有的游戏类APP中比较常见,拖动事件发生时,通过translationInView的方法,可以得到一个CGPoint类型的返回值,即位置的偏移量,可以根据偏移量修改对应的UI控件的center属性从而实现UI控件的位置移动效果。
//拖动手势
UIPanGestureRecognizer *panGesture=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
[self.imageView addGestureRecognizer:panGesture];
-(void)pan:(UIPanGestureRecognizer*)gesture{
//获取位置变化量
CGPoint translation=[gesture translationInView:self.view];
gesture.view.center=CGPointMake(gesture.view.center.x+translation.x, gesture.view.center.y+translation.y);
//要重置一下gesture的位置变化量
[gesture setTranslation:CGPointZero inView:self.view];
}
拖动手势存在的时候,似乎滑动手势就不起作用了。
长按手势
通过长按手势(UILongPressGestureRecognizer)可以监控手势作用于UI控件的开始长按、长按过程中以及松开等状态,并且设置不同的动作。最常见的应用案例可以参考微信的对讲模式,按住按钮即可开始录音,松开后结束录音并发送给对方。长按手势一定需要和UIGestureRecognizer类的state属性进行配合使用,即通过不同状态state下,实现不同的功能。UIGestureRecognizer类的state属性中,常见的有,其实UIGestureRecognizer的所有子类都有这个属性:
UIGestureRecognizerStateBegan:开始手势事件
UIGestureRecognizerStateEnded:结束手势事件
UIGestureRecognizerStateChanged:手势位置发生变化
UIGestureRecognizerStateFailed:无法识别的手势
//长按手势
UILongPressGestureRecognizer *longPressGesture=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
[self.imageView addGestureRecognizer:longPressGesture];
-(void)longPress:(UILongPressGestureRecognizer*)gesture{
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
NSLog(@"开始长按");
self.stateLabel.text=[NSString stringWithFormat:@"开始长按......"];
break;
case UIGestureRecognizerStateEnded:
NSLog(@"结束长按");
self.stateLabel.text=@"结束长按";
break;
default:
NSLog(@"长按中");
self.stateLabel.text=@"长按中";
break;
}
}
代码:https://github.com/ShaeZhuJiu/UIGestureRecognizer_base.git