概要
本章主要学习了IOS开发中的触摸手势以及图形变换的知识,其中手势包括单击、双击、长按、拖动、滑动、缩放、旋转,图形变化主要使用放射矩阵的平移、缩放和旋转。
使用手势时应该注意手势是指定到特定的视图(UIView)上的,因此一个手势只能对应一个视图(手势里面的view属性可获取其所所对应的视图),而一个View可以添加多个手势。同时,因为有的手势之间有冲突的,比如单击和双击,滑动和拖动。针对这种情形需要使用手势的依赖性特性做出区分,改特性要求特定手势失败后才触发该手势。
仿射矩阵变化应该注意到是通过视图的变化而达到显示效果的,同时还要注意到UIKit坐标和绘图坐标之间的差异。
结果展示
流程概要
1.手势是针对特定视图的,所以在学习过程中我都是在一个视图类里面做实验的,该类是一个UIView的子类。
2.IOS的手势分为以下几个,其分别对应一个类:
- UITapGestureRecognizer (单击和双击,根据setNumberOfTapsRequired设置区分)
- UIPinchGestureRecognizer
(缩放手势)- UIRotationGestureRecognizer
(旋转手势)- UISwipeGestureRecognizer
(滑动手势)- UIPanGestureRecognizer
(拖动手势)- UILongPressGestureRecognizer
(长安手势)一个滑动手势的对象只支持一个方向,默认是右滑,如果想要支持四个方向,那就需要添加四个滑动手势的对象,同时通过属性direction指定。
3.添加手势到视图可使用下述模板代码
/** 滑动 */ _swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(onSwipeGesture:)]; /** 设置手滑方向,只支持一个方向,默认是右滑 */ _swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp; [_imageView addGestureRecognizer:_swipeGestureRecognizer];注意要使的视图支持手势对象,需要启动支持手势属性,将属性userInteractionEnabled设为YES。
4.图形变化中注意到有CGAffineTransformMakeRotation和CGAffineTransformRotate类似的成对出现,其中前者有Make表示新建一个默认的矩阵,然后设置属性,而后者则是在指定的矩阵上添加属性特征,所以大部分使用类似于后者的仿射变换函数。使用例子如下
/** 设置(之前设置的其他矩阵属性重新变为默认值)矩阵 */ //CGAffineTransform t = CGAffineTransformMakeRotation(angle); /** 修改矩阵旋转属性 */ CGAffineTransform t = CGAffineTransformRotate(_imageView.transform, angle); self.imageView.transform = t;5.缩放手势(UIPinchGestureRecognizer)对象有属性scale,该属性表示缩放系数,所以在响应缩放手势的方法中可直接读取该属性设置缩放,不过使用完毕后注意将该值重置为1,如:
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale); recognizer.scale = 1;6.旋转手势(UIRotationGestureRecognizer)对象有属性rotation,该属性表示旋转属性值,所以在响应旋转手势的方法中可直接使用该属性值设置视图的旋转,注意重置0,如
ecognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation); recognizer.rotation = 0;7.拖动手势(UIPanGestureRecognizer)对象通过方法translationInView获取拖动后的参数,使用例子如下
CGPoint translation = [recognizer translationInView:self]; recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y); [recognizer setTranslation:CGPointZero inView:self];
主要代码
视图类文件
// // PickView.m // Gesture // // Created by arbboter on 14/12/19. // Copyright (c) 2014年 arbboter. All rights reserved. // #import "PickView.h" @interface PickView () @property (nonatomic, retain) UIImageView* imageView; @property (nonatomic, retain) UITapGestureRecognizer* tapSingleGestureRecognizer; @property (nonatomic, retain) UITapGestureRecognizer* tapDoubleGestureRecognizer; @property (nonatomic, retain) UIPinchGestureRecognizer* pinchGestureRecognizer; @property (nonatomic, retain) UIRotationGestureRecognizer* rotationGestureRecognizer; @property (nonatomic, retain) UISwipeGestureRecognizer* swipeGestureRecognizer; @property (nonatomic, retain) UIPanGestureRecognizer* panGestureRecognizer; @property (nonatomic, retain) UILongPressGestureRecognizer* longPressGestureRecognizer; @end @implementation PickView -(void) viewImageNamed:(NSString*)imageName { self.layer.borderWidth = 1; _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.frame.size.height/4, 200, 200)]; _imageView.image = [UIImage imageNamed:imageName]; _imageView.contentMode = UIViewContentModeScaleAspectFit; /** * UIViewContentModeScaleToFill, // 默认缩放方式,上下左右填充 [部分] UIViewContentModeScaleAspectFit, // 等比例缩放,一般效果是按照小的方向缩放 [全图] UIViewContentModeScaleAspectFill, // 等比例缩放,一般效果是按照小的方向缩放(会出现剪裁效果)[部分] UIViewContentModeRedraw, // 视图的bounds变化时重绘 UIViewContentModeCenter, // 放在视图的bounds的中间,保持等比例 [部分] UIViewContentModeTop, UIViewContentModeBottom, UIViewContentModeLeft, UIViewContentModeRight, UIViewContentModeTopLeft, UIViewContentModeTopRight, UIViewContentModeBottomLeft, UIViewContentModeBottomRight */ [self addSubview:_imageView]; /** 单击 */ _tapSingleGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapSingleGesture:)]; [_tapSingleGestureRecognizer setNumberOfTapsRequired:1]; [_imageView addGestureRecognizer:_tapSingleGestureRecognizer]; /** 双击 */ _tapDoubleGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapDoubleGesture:)]; [_tapDoubleGestureRecognizer setNumberOfTapsRequired:2]; [_imageView addGestureRecognizer:_tapDoubleGestureRecognizer]; /** 因为双击和单击存在冲突,所以需要设定没有双击才识别为单击 */ [_tapSingleGestureRecognizer requireGestureRecognizerToFail:_tapDoubleGestureRecognizer]; /** 缩放 */ _pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPinchGesture:)]; [_imageView addGestureRecognizer:_pinchGestureRecognizer]; /** 旋转 */ _rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(onRotationGesture:)]; [_imageView addGestureRecognizer:_rotationGestureRecognizer]; /** 滑动 */ _swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(onSwipeGesture:)]; /** 设置手滑方向,只支持一个方向,默认是右滑 */ _swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp; [_imageView addGestureRecognizer:_swipeGestureRecognizer]; /** 拖动 */ _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPanGesture:)]; [_imageView addGestureRecognizer:_panGestureRecognizer]; /** 拖动和滑动有冲突,有限响应滑动 */ [_panGestureRecognizer requireGestureRecognizerToFail:_swipeGestureRecognizer]; /** 长按 */ _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; [_imageView addGestureRecognizer:_longPressGestureRecognizer]; /** 图片视图启动触摸交互 */ _imageView.userInteractionEnabled = YES; } -(void) viewRotate:(CGFloat)angle { /** 设置(之前设置的其他矩阵属性重新变为默认值)矩阵 */ //CGAffineTransform t = CGAffineTransformMakeRotation(angle); /** 修改矩阵旋转属性 */ CGAffineTransform t = CGAffineTransformRotate(_imageView.transform, angle); self.imageView.transform = t; } -(void) viewTranslationX:(CGFloat)x Y:(CGFloat)y { /** 修改矩阵平移属性 */ CGAffineTransform t = CGAffineTransformTranslate(_imageView.transform, x, y); self.imageView.transform = t; } -(void) viewScaleX:(CGFloat)x Y:(CGFloat)y { /** 修改矩阵缩放属性 */ CGAffineTransform t = CGAffineTransformScale(_imageView.transform, x, y); self.imageView.transform = t; } #pragma 响应手势 - (void)onTapSingleGesture:(UITapGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); /** do nothing */ } - (void)onTapDoubleGesture:(UITapGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); CGFloat x = self.superview.frame.size.width/_imageView.frame.size.width; CGFloat y = self.superview.frame.size.height/_imageView.frame.size.height; [self viewTranslationX:self.superview.frame.size.width-self.frame.size.width Y:0]; NSLog(@"%.2f %.2f", _imageView.center.x, _imageView.center.y); // 缩放 if(x==1) { [self viewScaleX:0.5 Y:0.5]; } // 放大 else { x = x > y ? y : x; [self viewScaleX:x Y:x]; } /** 左边界对齐 */ _imageView.center = CGPointMake(_imageView.frame.size.width/2, _imageView.frame.size.height/2 + self.superview.frame.size.height/4); x = _imageView.frame.origin.x; [self viewTranslationX:-x Y:0]; } - (void)onPinchGesture:(UIPinchGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); /** 缩放图片 */ recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale); recognizer.scale = 1; } - (void)onRotationGesture:(UIRotationGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); /** 旋转 */ recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation); recognizer.rotation = 0; } - (void)onSwipeGesture:(UISwipeGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); /** 上滑修改父视图背景色 */ if(recognizer.direction == UISwipeGestureRecognizerDirectionUp) { CGFloat color[3] = {0}; color[0] = (arc4random()%50 + 1)/100.0; color[1] = (arc4random()%50 + 1)/100.0; color[2] = 1 - color[0] - color[1]; self.superview.backgroundColor = [UIColor colorWithRed:color[0] green:color[1] blue:color[2] alpha:1.0]; } } - (void)onPanGesture:(UIPanGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); /** 拖动图片 */ CGPoint translation = [recognizer translationInView:self]; recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y); [recognizer setTranslation:CGPointZero inView:self]; } - (void)onLongPressGesture:(UILongPressGestureRecognizer*) recognizer { NSLog(@"%s", __FUNCTION__); /** 防止同一时间多次调用 */ if(recognizer.state == UIGestureRecognizerStateBegan) { /** 弹出编辑选项 */ UIActionSheet* action = [[UIActionSheet alloc] initWithTitle:@"Edit Options" delegate:nil cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Show details" otherButtonTitles:@"Delete", @"Modify", @"Send", nil]; [action showInView:self]; [action release]; } } -(void) dealloc { [_imageView release]; [self removeGestureRecognizer:_tapSingleGestureRecognizer]; [self removeGestureRecognizer:_tapDoubleGestureRecognizer]; [self removeGestureRecognizer:_pinchGestureRecognizer]; [self removeGestureRecognizer:_rotationGestureRecognizer]; [self removeGestureRecognizer:_swipeGestureRecognizer]; [self removeGestureRecognizer:_panGestureRecognizer]; [self removeGestureRecognizer:_longPressGestureRecognizer]; [_tapSingleGestureRecognizer release]; [_tapDoubleGestureRecognizer release]; [_pinchGestureRecognizer release]; [_rotationGestureRecognizer release]; [_swipeGestureRecognizer release]; [_panGestureRecognizer release]; [_longPressGestureRecognizer release]; [super dealloc]; } @end
项目工程