iOS 手势识别与操作 UIGestureRecognizer
来源:互联网 发布:淘宝客服绩效管理 编辑:程序博客网 时间:2024/05/16 07:03
1.UIGestureRecognizer
- UITapGestureRecognizer 轻拍手势
- UIPinchGestureRecognizer 捏合缩放
- UIRotationGestureRecognizer 旋转
- UISwipeGestureRecognizer 轻扫滑动
- UIPanGestureRecognizer 拖移
- UILongPressGestureRecognizer 长按
2.注意事项
当为手势添加回调方法时,手势开始,改变、或结束时,回调方法被调用,有的时候只需要调用一次方法,可以用gesture的state属性来判断,如if (gesture.state == UIGestureRecognizerStateBegan) {}
3.TapGesture
self.view.backgroundColor = [UIColor lightGrayColor]; self.gv.layer.borderWidth = 2; self.gv.layer.cornerRadius = 6; // 设置gv控件支持用户交互 self.gv.userInteractionEnabled = YES; // 设置gv控件支持多点触碰 self.gv.multipleTouchEnabled = YES; for (int i = 1 ; i < 6 ; i++) { // 创建手势处理器,指定使用该控制器的handleTap:方法处理手势 UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; // 设置该点击手势处理器只处理i次连击事件 gesture.numberOfTapsRequired = i; // 设置该点击手势处理器只处理2个手指的触碰事件 gesture.numberOfTouchesRequired = 1; // 为gv控件添加手势处理器。 [self.gv addGestureRecognizer:gesture]; }}// 实现手势处理器的方法,该方法应该声明一个形参。// 当该方法被激发时,手势处理器会作为参数传给该方法的参数。- (void) handleTap:(UITapGestureRecognizer*)gesture{ NSUInteger touchNum = gesture.numberOfTouches; NSUInteger tapNum = gesture.numberOfTapsRequired; self.label.text = [NSString stringWithFormat: @"用户使用%lu个手指进行触碰,触碰次数为:%lu" , touchNum , tapNum]; // 指定2秒后清除label的文本 [self.label performSelector:@selector(setText:) withObject:@"" afterDelay:2];}
4.PinchGesture
- (void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = [UIColor lightGrayColor]; self.gv.layer.borderWidth = 2; self.gv.layer.cornerRadius = 6; // 设置gv控件支持用户交互 self.gv.userInteractionEnabled = YES; // 设置gv控件支持多点触碰 self.gv.multipleTouchEnabled = YES; // 创建手势处理器,指定使用该控制器的handlePinch:方法处理手势 UIPinchGestureRecognizer* gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; // 为gv控件添加手势处理器。 [self.gv addGestureRecognizer:gesture];}// 实现手势处理器的方法,该方法应该声明一个形参。// 当该方法被激发时,手势处理器会作为参数传给该方法的参数。- (void) handlePinch:(UIPinchGestureRecognizer*)gesture{ // 获取用户捏合的速度和比例 CGFloat velocity = gesture.velocity; CGFloat scale = gesture.scale; self.label.text = [NSString stringWithFormat: @"用户捏合的速度为%g、比例为%g" , velocity , scale]; // 指定2秒后清除label的文本 //[self.label performSelector:@selector(setText:) // withObject:@"" afterDelay:2];}
5.RotationGesture 仿iPhone相册图片捏合旋转
1.扩展UIImage:UIImage+CWCategory
UIImage+CWCategory.h
@interface UIImage (CWCategory)// 对指定UI控件进行截图+ (UIImage*)captureView:(UIView *)targetView;//+ (UIImage*)captureScreen;// 定义一个方法用于“挖取”图片的指定区域- (UIImage *)imageAtRect:(CGRect)rect;// 保持图片纵横比缩放,最短边必须匹配targetSize的大小// 可能有一条边的长度会超过targetSize指定的大小- (UIImage *)imageByScalingAspectToMinSize:(CGSize)targetSize;// 保持图片纵横比缩放,最长边匹配targetSize的大小即可// 可能有一条边的长度会小于targetSize指定的大小- (UIImage *)imageByScalingAspectToMaxSize:(CGSize)targetSize;// 不保持图片纵横比缩放- (UIImage *)imageByScalingToSize:(CGSize)targetSize;// 对图片按弧度执行旋转- (UIImage *)imageRotatedByRadians:(CGFloat)radians;// 对图片按角度执行旋转- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees;- (void) saveToDocuments:(NSString*)fileName;@end
UIImage+CWCategory.m:
#import "UIImage+CWCategory.h"#import <QuartzCore/QuartzCore.h>//extern CGImageRef UIGetScreenImage();@implementation UIImage (CWCategory)//+ (UIImage*)captureScreen//{// // 需要先声明该外部函数// extern CGImageRef UIGetScreenImage();// // 调用UIGetScreenImage()函数执行截屏// CGImageRef screen = UIGetScreenImage();// // 获取截屏得到的图片// UIImage* newImage = [UIImage imageWithCGImage:screen];// return newImage;//}+ (UIImage*)captureView:(UIView *)targetView{ // 获取目标UIView的所在的区域 CGRect rect = targetView.frame; // 开始绘图 UIGraphicsBeginImageContext(rect.size); // 获取当前的绘图Context CGContextRef context = UIGraphicsGetCurrentContext(); // 调用CALayer的方法将当前控件绘制到绘图Context中 [targetView.layer renderInContext:context]; // 获取该绘图Context中的图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage;}-(UIImage *)imageAtRect:(CGRect)rect{ // 获取该UIImage图片对应的CGImageRef对象 CGImageRef srcImage = [self CGImage]; // 从srcImage中“挖取”rect区域 CGImageRef imageRef = CGImageCreateWithImageInRect(srcImage, rect); // 将“挖取”出来的CGImageRef转换为UIImage对象 UIImage* subImage = [UIImage imageWithCGImage: imageRef]; CGImageRelease(srcImage); CGImageRelease(imageRef); return subImage;}- (UIImage *)imageByScalingAspectToMinSize:(CGSize)targetSize{ // 获取源图片的宽和高 CGSize imageSize = self.size; CGFloat width = imageSize.width; CGFloat height = imageSize.height; // 获取图片缩放目标大小的宽和高 CGFloat targetWidth = targetSize.width; CGFloat targetHeight = targetSize.height; // 定义图片缩放后的宽度 CGFloat scaledWidth = targetWidth; // 定义图片缩放后的高度 CGFloat scaledHeight = targetHeight; CGPoint anchorPoint = CGPointZero; // 如果源图片的大小与缩放的目标大小不相等 if (!CGSizeEqualToSize(imageSize, targetSize)) { // 计算水平方向上的缩放因子 CGFloat xFactor = targetWidth / width; // 计算垂直方向上的缩放因子 CGFloat yFactor = targetHeight / height; // 定义缩放因子scaleFactor,为两个缩放因子中较大的一个 CGFloat scaleFactor = xFactor > yFactor? xFactor : yFactor; // 根据缩放因子计算图片缩放后的宽度和高度 scaledWidth = width * scaleFactor; scaledHeight = height * scaleFactor; // 如果横向上的缩放因子大于纵向上的缩放因子,那么图片在纵向上需要裁切 if (xFactor > yFactor) { anchorPoint.y = (targetHeight - scaledHeight) * 0.5; } // 如果横向上的缩放因子小于纵向上的缩放因子,那么图片在横向上需要裁切 else if (xFactor < yFactor) { anchorPoint.x = (targetWidth - scaledWidth) * 0.5; } } // 开始绘图 UIGraphicsBeginImageContext(targetSize); // 定义图片缩放后的区域 CGRect anchorRect = CGRectZero; anchorRect.origin = anchorPoint; anchorRect.size.width = scaledWidth; anchorRect.size.height = scaledHeight; // 将图片本身绘制到auchorRect区域中 [self drawInRect:anchorRect]; // 获取绘制后生成的新图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // 返回新图片 return newImage ;}- (UIImage *)imageByScalingAspectToMaxSize:(CGSize)targetSize{ // 获取源图片的宽和高 CGSize imageSize = self.size; CGFloat width = imageSize.width; CGFloat height = imageSize.height; // 获取图片缩放目标大小的宽和高 CGFloat targetWidth = targetSize.width; CGFloat targetHeight = targetSize.height; // 定义图片缩放后的实际的宽和高度 CGFloat scaledWidth = targetWidth; CGFloat scaledHeight = targetHeight; CGPoint anchorPoint = CGPointZero; // 如果源图片的大小与缩放的目标大小不相等 if (!CGSizeEqualToSize(imageSize, targetSize)) { CGFloat xFactor = targetWidth / width; CGFloat yFactor = targetHeight / height; // 定义缩放因子scaleFactor,为两个缩放因子中较小的一个 CGFloat scaleFactor = xFactor < yFactor ? xFactor:yFactor; // 根据缩放因子计算图片缩放后的宽度和高度 scaledWidth = width * scaleFactor; scaledHeight = height * scaleFactor; // 如果横向的缩放因子小于纵向的缩放因子,图片在上面、下面有空白 // 那么图片在纵向上需要下移一段距离,保持图片在中间 if (xFactor < yFactor) { anchorPoint.y = (targetHeight - scaledHeight) * 0.5; } // 如果横向的缩放因子小于纵向的缩放因子,图片在左边、右边有空白 // 那么图片在横向上需要右移一段距离,保持图片在中间 else if (xFactor > yFactor) { anchorPoint.x = (targetWidth - scaledWidth) * 0.5; } } // 开始绘图 UIGraphicsBeginImageContext(targetSize); // 定义图片缩放后的区域 CGRect anchorRect = CGRectZero; anchorRect.origin = anchorPoint; anchorRect.size.width = scaledWidth; anchorRect.size.height = scaledHeight; // 将图片本身绘制到auchorRect区域中 [self drawInRect:anchorRect]; // 获取绘制后生成的新图片 UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // 返回新图片 return newImage ;}- (UIImage *)imageByScalingToSize:(CGSize)targetSize{ // 开始绘图 UIGraphicsBeginImageContext(targetSize); // 定义图片缩放后的区域,因此无需保持纵横比,所以直接缩放 CGRect anchorRect = CGRectZero; anchorRect.origin = CGPointZero; anchorRect.size = targetSize; // 将图片本身绘制到auchorRect区域中 [self drawInRect:anchorRect]; // 获取绘制后生成的新图片 UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // 返回新图片 return newImage;}// 图片旋转角度- (UIImage *)imageRotatedByRadians:(CGFloat)radians{ // 定义一个执行旋转的CGAffineTransform结构体 CGAffineTransform t = CGAffineTransformMakeRotation(radians); // 对图片的原始区域执行旋转,获取旋转后的区域 CGRect rotatedRect = CGRectApplyAffineTransform( CGRectMake(0.0 , 0.0, self.size.width, self.size.height) , t); // 获取图片旋转后的大小 CGSize rotatedSize = rotatedRect.size; // 创建绘制位图的上下文 UIGraphicsBeginImageContext(rotatedSize); CGContextRef ctx = UIGraphicsGetCurrentContext(); // 指定坐标变换,将坐标中心平移到图片的中心 CGContextTranslateCTM(ctx, rotatedSize.width/2, rotatedSize.height/2); // 执行坐标变换,旋转过radians弧度 CGContextRotateCTM(ctx , radians); // 执行坐标变换,执行缩放 CGContextScaleCTM(ctx, 1.0, -1.0); // 绘制图片 CGContextDrawImage(ctx, CGRectMake(-self.size.width / 2 , -self.size.height / 2, self.size.width, self.size.height), self.CGImage); // 获取绘制后生成的新图片 UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // 返回新图片 return newImage;}- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees{ return [self imageRotatedByRadians:degrees * M_PI / 180];}- (void) saveToDocuments:(NSString*)fileName{ // 获取当前应用路径下的Documents目录下的指定文件名对应的文件路径 NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:fileName]; // 保存PNG图片 [UIImagePNGRepresentation(self) writeToFile:path atomically:YES];// // 保存JPG图片 // [UIImageJPEGRepresentation(self, 1.0) // 1.0代表图片压缩比率// writeToFile:path atomically:YES];}@end
ViewController:
#import "UIImage+CWCategory.h"#define PI 3.141592653#define degtorad(X) ((X)/180*PI)#define radtodeg(X) ((X)*180/PI)@interface ViewController ()@property (strong, nonatomic) IBOutlet UIImageView *imageView;@end@implementation ViewControllerUIImage* srcImage;CGFloat currentScale;CGFloat currentRotation;- (void)viewDidLoad{ [super viewDidLoad]; [UIApplication sharedApplication].statusBarHidden = YES; srcImage = [UIImage imageNamed:@"seashore.png"]; // 设置图片直接显示在中间(不进行任何缩放) self.view.contentMode = UIViewContentModeCenter; // 设置imageView初始显示的图片 self.imageView.image = srcImage; // 设置初始的缩放比例 currentScale = 1; currentRotation = 0; // 设置imageView允许用户交互,支持多点触碰 self.imageView.userInteractionEnabled = YES; self.imageView.multipleTouchEnabled = YES; // 创建UIPinchGestureRecognizer手势处理器,该手势处理器激发scaleImage:方法 UIPinchGestureRecognizer* gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(scaleImage:)]; // 为imageView添加手势处理器 [self.imageView addGestureRecognizer:gesture]; // 创建UIRotationGestureRecognizer手势处理器,该手势处理器激发rotateImage:方法 UIRotationGestureRecognizer* rotateGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotateImage:)]; // 为imageView添加手势处理器 [self.imageView addGestureRecognizer:rotateGesture];}- (void) scaleImage:(UIPinchGestureRecognizer*)gesture{ CGFloat scale = gesture.scale; // 根据手势处理器的缩放比计算图片缩放后的目标大小 CGSize targetSize = CGSizeMake(srcImage.size.width * scale * currentScale, srcImage.size.height * scale * currentScale); // 对图片进行缩放、旋转 self.imageView.image = [[srcImage imageByScalingToSize:targetSize] imageRotatedByRadians:currentRotation]; // 如果手势结束 if(gesture.state == UIGestureRecognizerStateEnded) { // 计算结束时候图片的缩放比 currentScale = scale * currentScale; }}- (void) rotateImage:(UIRotationGestureRecognizer*)gesture{ // 获取手势旋转的弧度 CGFloat rotation = gesture.rotation; //NSLog(@"rotation %f",rotation); //NSLog(@"du %f",radtodeg(rotation)); // 根据当前缩放比计算图片缩放后的目标大小 CGSize targetSize = CGSizeMake(srcImage.size.width * currentScale, srcImage.size.height * currentScale); // 对图片进行缩放、旋转 self.imageView.image = [[srcImage imageByScalingToSize:targetSize] imageRotatedByRadians:currentRotation + rotation]; // 如果旋转手势结束 if(gesture.state == UIGestureRecognizerStateEnded) { currentRotation = currentRotation + rotation; }}@end
6.SwipeGesture
- (void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = [UIColor lightGrayColor]; self.gv.layer.borderWidth = 2; self.gv.layer.cornerRadius = 6; // 设置gv控件支持用户交互 self.gv.userInteractionEnabled = YES; // 设置gv控件支持多点触碰 self.gv.multipleTouchEnabled = YES; for (int i = 0 ; i < 4 ; i++) { // 创建手势处理器,指定使用该控制器的handleSwipe:方法处理轻扫手势 UISwipeGestureRecognizer* gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)]; // 设置该点击手势处理器只处理i个手指的轻扫手势 gesture.numberOfTouchesRequired = 1; // 指定该手势处理器只处理1 << i方向的轻扫手势 gesture.direction = 1<<i; // 为gv控件添加手势处理器。 [self.gv addGestureRecognizer:gesture]; }}// 实现手势处理器的方法,该方法应该声明一个形参。// 当该方法被激发时,手势处理器会作为参数传给该方法的参数。- (void) handleSwipe:(UISwipeGestureRecognizer*)gesture{ // 获取轻扫手势的方向 NSUInteger direction = gesture.direction; // 根据手势方向的值得到方向字符串 NSString* dirStr = direction == UISwipeGestureRecognizerDirectionRight ? @"向右" : (direction == UISwipeGestureRecognizerDirectionLeft ? @"向左" : (direction == UISwipeGestureRecognizerDirectionUp ? @"向上" :@"向下")); NSUInteger touchNum = gesture.numberOfTouchesRequired; self.label.text = [NSString stringWithFormat: @"用户使用%lu个手指进行轻扫,方向为:%@" , (unsigned long)touchNum , dirStr]; // 指定2秒后清除label的文本 [self.label performSelector:@selector(setText:) withObject:@"" afterDelay:2];}
7.PanGesture
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
self.gv.layer.borderWidth = 2;
self.gv.layer.cornerRadius = 6;
// 设置gv控件支持用户交互
self.gv.userInteractionEnabled = YES;
// 设置gv控件支持多点触碰
self.gv.multipleTouchEnabled = YES;
// 创建手势处理器,指定使用该控制器的handlePan:方法处理手势
UIPanGestureRecognizer* gesture = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:@selector(handlePan:)];
// 设置该拖动手势处理器至少需要1个手指
gesture.minimumNumberOfTouches = 1;
// 设置该拖动手势处理器最多需要2个手指
gesture.maximumNumberOfTouches = 2;
// 为gv控件添加手势处理器。
[self.gv addGestureRecognizer:gesture];
}
// 实现手势处理器的方法,该方法应该声明一个形参。
// 当该方法被激发时,手势处理器会作为参数传给该方法的参数。 - (void) handlePan:(UIPanGestureRecognizer*)gesture
{
CGPoint velocity = [gesture velocityInView:self.gv];
CGPoint translation = [gesture translationInView:self.gv];
self.label.text = [NSString stringWithFormat:
@”水平速度为:%g, 垂直速度为:%g, 水平位移为:%g, 垂直位移为:%g”
, velocity.x , velocity.y
, translation.x , translation.y];
// 指定2秒后清除label的文本
//[self.label performSelector:@selector(setText:)
// withObject:@”” afterDelay:2];
}
8.LongPressGesture
#define BUTTON_WIDTH 80#define BUTTON_HEIGHT 30@implementation ViewControllerNSInteger bnIndex;- (void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = [UIColor lightGrayColor]; // 创建一个手势处理器,用于检测、处理长按手势 UILongPressGestureRecognizer* gesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)]; // 为该控件添加手势处理器 [self.view addGestureRecognizer:gesture];}- (void) panAction:(UIPanGestureRecognizer*)gesture { CGPoint point = [gesture locationInView:self.view]; UIButton * btn = (UIButton*)[gesture view]; [btn setFrame:CGRectMake(point.x - BUTTON_WIDTH/2 , point.y - BUTTON_HEIGHT/2, BUTTON_WIDTH, BUTTON_HEIGHT)];}- (void) longPress:(UILongPressGestureRecognizer*)gesture{ CGPoint point = [gesture locationInView:self.view]; , UIButton* bn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // 为该按钮设置文本 [bn setTitle:[NSString stringWithFormat:@"按钮%ld", (long)bnIndex] forState:UIControlStateNormal]; // 设置该bn按钮的大小和位置 bn.frame = CGRectMake( point.x,point.y, BUTTON_WIDTH , BUTTON_HEIGHT); // 为该按钮添加事件处理方法 [bn addTarget:self action:@selector(remove:) forControlEvents:UIControlEventTouchUpInside]; // 将按钮添加到应用界面的UIView控件中 [self.view addSubview:bn]; UIPanGestureRecognizer * panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)]; [bn addGestureRecognizer:panGesture]; bnIndex ++; }}- (void) remove:(UIButton*)sender{ for (UIGestureRecognizer * ges in [sender gestureRecognizers]) { [sender removeGestureRecognizer:ges]; } // 删除事件源控件(激发该事件的按钮) [sender removeFromSuperview];}@end
9.手势的依赖
[A requireGestureRecognizerToFail:B]函数,它可以指定当A手势发生时,即便A已经滿足条件了,也不会立刻触发,会等到指定的手势B确定失败之后才触发。
- (void)viewDidLoad { [super viewDidLoad]; // 轻拍1次 UITapGestureRecognizer* tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(SingleTap:)]; //点击的次数 tap1.numberOfTapsRequired = 1; //给self.view添加一个手势监测; [self.view addGestureRecognizer:tap1]; // 轻拍2次 UITapGestureRecognizer* tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(DoubleTap:)]; tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(DoubleTap:)]; tap2.numberOfTapsRequired = 2; [self.view addGestureRecognizer:tap2]; // 手势互斥或依赖,双击手势确定监测失败才会触发单击手势的相应操作 [tap1 requireGestureRecognizerToFail:tap2];}-(void)SingleTap:(UITapGestureRecognizer*)recognizer{ NSLog(@"轻拍1次");}-(void)DoubleTap:(UITapGestureRecognizer*)recognizer{ NSLog(@"轻拍2次");}
0 0
- iOS 手势识别与操作 UIGestureRecognizer
- ios 手势识别UIGestureRecognizer
- iOS--手势识别UIGestureRecognizer
- UIGestureRecognizer 手势操作 iOS
- iOS手势操作UIGestureRecognizer
- UIGestureRecognizer iOS手势识别器
- iOS开发 - 手势识别(UIGestureRecognizer)
- iOS开发 手势识别UIGestureRecognizer
- iOS之UIGestureRecognizer手势识别
- iOS UIGestureRecognizer(手势操作)~demo
- iOS 笔记五:手势识别 UIGestureRecognizer
- iOS编程-------UIImageView、手势识别器UIGestureRecognizer
- iOS开发 - 手势识别(UIGestureRecognizer) --转载
- iOS 手势识别——UIGestureRecognizer
- IOS- ios的手势操作之UIGestureRecognizer
- ios的手势操作之UIGestureRecognizer浅析
- ios的手势操作之UIGestureRecognizer浅析
- ios的手势操作之UIGestureRecognizer浅析
- c++ primer第五版(中文)习题答案 第十章第二节第三小节-重排容器元素的算法
- ssh架构不能自动生成建表语句
- Robot framework中元素的定位
- 三层架构
- poj1434Fill the Cisterns!【二分+计算几何】
- iOS 手势识别与操作 UIGestureRecognizer
- c/c++ sort函数的用法
- 无法将参数 1 从“char ”转换为“LPWSTR”
- 使用MSScriptControl 在 C# 中读取json数据
- 个人学习过程中遇到的疑难杂症(笔记,持续更新中……)
- IP地址、子网掩码、网络号、主机号、网络地址、主机地址
- 搭建Spring、Spring MVC、Mybatis和Freemarker
- android ViewGroup的事件分发机制
- 前端相关-代码自动补全