码迷,mamicode.com
首页 > 其他好文 > 详细

手势与变形 、 视图与坐标系

时间:2015-12-15 21:16:23      阅读:479      评论:0      收藏:0      [点我收藏+]

标签:

1 使用点击手势实现单击和双击手势

1.1 问题

UITapGestureRecognizer点击手势,通常用于单击和双击某个视图。本案例使用UITapGestureRecognizer点击手势实现单击和双击,如图-1、图-2所示:

技术分享

图-1

技术分享

图-2

1.2 方案

首先创建Xcode项目,在Storyboard中拖放一个ImageView控件和Label控件,在右边栏设置好相关属性,此时注意将ImageView的用户交互功能打开,否则无法识别手势。

其次将ImageView和Label控件关联成TRViewController的属性imageView和label。在TRViewController类中的viewDidLoad方法中创建一个UITapGestureRecognizer手势tapGR,使用initWithTarget: action:方法进行初始化并添加事件方法tap:。

将tap手势的numberOfTapsRequired属性设置为1,表示点击一下的意思即单击。最后将手势添加到view中,实现方法tap:点击view则在label上显示“view被点击了一下”。

然后在TRViewController类中的viewDidLoad方法中创建一个UITapGestureRecognizer手势doubleTap,使用initWithTarget: action:方法进行初始化并添加事件方法doubleTap:。

将doubleTap手势的numberOfTapsRequired属性设置为2,表示点击两下的意思即双击。最后将手势添加到imageView中,实现方法doubletap:点击imageView则在label上显示“imageView被点击了两下”。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目搭建界面

首先创建Xcode项目,在Storyboard中拖放一个ImageView控件和Label控件,在右边栏设置好相关属性,此时注意将ImageView的用户交互功能打开,否则无法识别手势,如图-3所示:

技术分享

图-3

步骤二:创建单击手势,添加到界面

首先将ImageView和Label控件关联成TRViewController的属性imageView和label,代码如下所示:

 
  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  3. @property (weak, nonatomic) IBOutlet UILabel *label;
  4. @end

然后在TRViewController类中的viewDidLoad方法中创建一个UITapGestureRecognizer手势tapGR,使用initWithTarget: action:方法进行初始化并添加事件方法tap:,代码如下所示:

 
  1. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];

将tap手势的numberOfTapsRequired属性设置为1,表示点击一下的意思即单击。最后将手势添加到view中,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.     //创建手势对象
  5. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
  6. //设置相关属性
  7. tapGR.numberOfTapsRequired = 1;
  8. tapGR.numberOfTouchesRequired = 1;
  9. //将手势对象加入到需要识别手势的视图
  10. [self.view addGestureRecognizer:tapGR];
  11. }

最后实现方法tap:,当点击view则在label上显示“view被点击了一下”,代码如下所示:

  1. - (void)tap:(UITapGestureRecognizer *)gr
  2. {
  3. self.label.text = @"view被点击了一下";
  4. }

步骤三:创建双击手势,添加到界面

然后在TRViewController类中的viewDidLoad方法中创建一个UITapGestureRecognizer手势doubleTap,使用initWithTarget: action:方法进行初始化并添加事件方法doubleTap:,代码如下所示:

 
  1. UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTap:)];

将doubleTap手势的numberOfTapsRequired属性设置为2,表示点击两下的意思即双击。最后将手势添加到view中,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
  5. tapGR.numberOfTapsRequired = 1;
  6. tapGR.numberOfTouchesRequired = 1;
  7. [self.view addGestureRecognizer:tapGR];
  8. UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTap:)];
  9. [doubleTap setNumberOfTapsRequired:2];
  10. [self.imageView addGestureRecognizer:doubleTap];
  11. }

最后实现方法doubleap:,当点击imageView则在label上显示“imageView被点击了两下”,代码如下所示:

  1. -(void)doubleTap:(UITapGestureRecognizer*)gr {
  2. self.label.text = @"imageView被点击了两下";
  3. }

1.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController ()
  3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  4. @property (weak, nonatomic) IBOutlet UILabel *label;
  5. @end
  6. @implementation TRViewController
  7. - (void)viewDidLoad
  8. {
  9. [super viewDidLoad];
  10.     //1. 创建手势对象
  11. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
  12. //2. 设置相关属性
  13. tapGR.numberOfTapsRequired = 1;
  14. tapGR.numberOfTouchesRequired = 1;
  15. //3. 将手势对象加入到需要识别手势的视图
  16. [self.view addGestureRecognizer:tapGR];
  17. UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTap:)];
  18. [doubleTap setNumberOfTapsRequired:2];
  19. [self.imageView addGestureRecognizer:doubleTap];
  20. }
  21. - (void)tap:(UITapGestureRecognizer *)gr
  22. {
  23. self.label.text = @"view被点击了一下";
  24. }
  25. -(void)doubleTap:(UITapGestureRecognizer*)gr {
  26. self.label.text = @"imageView被点击了两下";
  27. }
  28. @end
 

2 使用轻扫手势切换两张图片

2.1 问题

UISwipeGestureRecognizer轻扫手势,通常用于翻书、翻页、切换画面等效果。本案例将使用UISwipeGestureRecognizer轻扫手势实现两张图片的切换显示,如图-4、图-5所示:

技术分享

图-4

技术分享

图-5

2.2 方案

首先创建Xcode项目,在Storyboard中拖放两个和屏幕一样大小的ImageView控件,在屏幕上叠放在一起。

其次在TRViewController类中的viewDidLoad方法中创建一个UISwipeGestureRecognizer手势swipeGR,使用initWithTarget: action:方法进行初始化并添加事件方法swipe:。

将swipe手势的direction属性设置为左右,表示从右向左轻滑或者由左向右轻滑都可以触发手势的动作事件。然后将手势添加到self.view中。

最后将手势添加到view中,实现方法swipe:,当滑动图片则切换两个ImageView的显示顺序。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目搭建界面

首先创建Xcode项目,在Storyboard中拖放两个和屏幕一样大小的ImageView控件,在屏幕上叠放在一起,如图-6所示:

技术分享

图-6

步骤二:创建swipe手势,添加到界面

在TRViewController类中的viewDidLoad方法中创建一个UISwipeGestureRecognizer手势swipeGR,使用initWithTarget: action:方法进行初始化并添加事件方法swipe:,代码如下所示:

  1. UISwipeGestureRecognizer *swipeGR = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];

将swipe手势的direction属性设置为左右,表示从右向左轻滑或者由左向右轻滑都可以触发手势的动作事件,并将手势添加到self.view中,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.     UISwipeGestureRecognizer *swipeGR = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
  5. swipeGR.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight ;
  6. [self.view addGestureRecognizer:swipeGR];
  7. }

步骤三:实现事件方法swipe:

实现方法swipe:,当滑动图片则切换两个ImageView的显示顺序,代码如下所示:

  1. - (void)swipe:(UISwipeGestureRecognizer *)gr
  2. {
  3. [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
  4. NSLog(@"%@",self.view.subviews);
  5. }

2.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @implementation TRViewController
  3. - (void)viewDidLoad
  4. {
  5. [super viewDidLoad];
  6.     UISwipeGestureRecognizer *swipeGR = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
  7. swipeGR.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight ;
  8. [self.view addGestureRecognizer:swipeGR];
  9. }
  10. - (void)swipe:(UISwipeGestureRecognizer *)gr
  11. {
  12. [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
  13. NSLog(@"%@",self.view.subviews);
  14. }
  15. @end
 

3 使用缩放手势改变textView的显示状态和字体大小

3.1 问题

UIPinchGestureRecognizer缩放手势,通常用于缩放图片或视图,本案例使用UIPinchGestureRecognizer缩放手势实现改变textView的字体大小,当缩小速度足够快时则隐藏textView,如图-7所示:

技术分享

图-7

3.2 方案

首先创建Xcode项目,在Storyboard中拖放一个适当大小的TextView控件,在右边栏的检查器四中设置好显示的文字内容和背景颜色。将TextView关联成TRViewControlle的属性textView。

然后在TRViewController类中的viewDidLoad方法中创建一个UIPinchGestureRecognizer手势pinchGR,使用initWithTarget: action:方法进行初始化并添加事件方法pinch:。将pinchGR添加到self.view中。

UIPinchGestureRecognizer类型的手势有两个常用的属性scale和velocity,scale表示缩放的比例,velocity表示缩放的速度。这两个属性都为只读属性。

最后实现pinch:方法,该方法中根据velocity属性的值判断是否显示textView,根据scale属性的值计算textView的字体大小。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目搭建界面

首先创建Xcode项目,在Storyboard中拖放一个适当大小的TextView控件,在右边栏的检查器四中设置好显示的文字内容和背景颜色。将TextView关联成TRViewControlle的属性textView,代码如下所示:

 
  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet UITextView *textView;
  3. @end

步骤二:创建pinch手势,添加到界面

在TRViewController类中的viewDidLoad方法中创建一个UIPinchGestureRecognizer手势pinchGR,使用initWithTarget: action:方法进行初始化并添加事件方法pinch:,并将pinchGR添加到self.view中,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.     UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
  5. [self.view addGestureRecognizer:pinchGR];
  6. }

步骤三:实现事件方法pinch:

实现pinch:方法,该方法中根据velocity属性的值判断是否显示textView,当velocity的值小于-10时则隐藏textView,大于10 则显示textView。再根据scale属性的值计算textView的字体大小,代码如下所示:

 
  1. - (void)pinch:(UIPinchGestureRecognizer *)gr
  2. {
  3. if (gr.velocity < -10) {
  4. self.textView.hidden = YES;
  5. }else if (gr.velocity > 10) {
  6. self.textView.hidden = NO;
  7. }else{
  8. self.textView.font = [UIFont systemFontOfSize:17 * gr.scale];
  9. }
  10. }

3.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController ()
  3. @property (weak, nonatomic) IBOutlet UITextView *textView;
  4. @end
  5. @implementation TRViewController
  6. - (void)viewDidLoad
  7. {
  8. [super viewDidLoad];
  9.     UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
  10. [self.view addGestureRecognizer:pinchGR];
  11. }
  12. - (void)pinch:(UIPinchGestureRecognizer *)gr
  13. {
  14. if (gr.velocity < -10) {
  15. self.textView.hidden = YES;
  16. }else if (gr.velocity > 10) {
  17. self.textView.hidden = NO;
  18. }else{
  19. self.textView.font = [UIFont systemFontOfSize:17 * gr.scale];
  20. }
  21. }
  22. @end
 

4 使用拖动手势移动图片

4.1 问题

UIPanGestureRecognizer拖动手势,通常用于移动某个视图的位置,本案例使用UIPanGestureRecognizer拖动手势移动图片,根据手指触屏的坐标改变图片的位置,如图-8、图-9所示:

技术分享

图-8

技术分享

图-9

4.2 方案

首先创建Xcode项目,在Storyboard中拖放一个适当大小的ImageView控件,在右边栏的检查器四中设置好显示图片。将ImageView控件关联成TRViewControlle的属性imageView。

然后在TRViewController类中的viewDidLoad方法中创建一个UIPanGestureRecognizer手势panGR,使用initWithTarget: action:方法进行初始化并添加事件方法pan:。将panGR添加到self.view中。

所有的手势都有一个UIGestureRecognizerState枚举类型的属性state,用来表示手势的状态,包括手势的开始、变化和结束。

最后实现pan:方法,该方法中根据手势不同的状态改变imageView的坐标和大小,使imageView的center根据手指触摸点改变。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建项目搭建界面

首先创建Xcode项目,在Storyboard中拖放一个适当大小的Imageview控件,在右边栏的检查器四中设置好显示图片。将ImageView控件关联成TRViewControlle的属性imageView,代码如下所示:

  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  3. @end

步骤二:创建pan手势,添加到界面

在TRViewController类中的viewDidLoad方法中创建一个UIPanGestureRecognizer手势panGR,使用initWithTarget: action:方法进行初始化并添加事件方法pan:,并将panGR添加到self.view中,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.     UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  5. panGR.minimumNumberOfTouches = 1;
  6. [self.view addGestureRecognizer:panGR];
  7. }

步骤三:实现事件方法pan:

实现pan:方法,该方法中根据手势不同的状态改变imageView的坐标和大小,使imageView的center根据手指触摸点改变。

当state的值等于UIGestureRecognizerStateBegan时将imageView的大小设置为原来大小的0.5倍,当state的值等于UIGestureRecognizerStateChanged时imageView的center跟着手指触摸点移动,当state的值等于UIGestureRecognizerStateEnded时imageView的大小变回原来的大小,代码如下所示:

 
  1. - (void)pan:(UIPanGestureRecognizer *)gr
  2. {
  3. if (gr.state == UIGestureRecognizerStateBegan) {
  4. self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width*0.5, self.imageView.frame.size.height*0.5);
  5. }else if(gr.state == UIGestureRecognizerStateChanged){
  6. self.imageView.center = [gr locationInView:self.view];
  7. }else if(gr.state == UIGestureRecognizerStateEnded){
  8. self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width*2, self.imageView.frame.size.height*2);
  9. }
  10. }

4.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController ()
  3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  4. @end
  5. @implementation TRViewController
  6. - (void)viewDidLoad
  7. {
  8. [super viewDidLoad];
  9.     UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  10. panGR.minimumNumberOfTouches = 1;
  11. [self.view addGestureRecognizer:panGR];
  12. }
  13. - (void)pan:(UIPanGestureRecognizer *)gr
  14. {
  15. if (gr.state == UIGestureRecognizerStateBegan) {
  16. self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width*0.5, self.imageView.frame.size.height*0.5);
  17. }else if(gr.state == UIGestureRecognizerStateChanged){
  18. self.imageView.center = [gr locationInView:self.view];
  19. }else if(gr.state == UIGestureRecognizerStateEnded){
  20. self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width*2, self.imageView.frame.size.height*2);
  21. }
  22. }
  23. @end

5 结合手势对图片进行缩放、旋转和位移

5.1 问题

变形transform是视图(View)的一个CGAffineTransform结构体类型的属性,可以使视图产生缩放、旋转、位移等变化。本案例结合手势实现对一张图片的变形,包括缩放、旋转和位移,如图-10、图-11所示:

技术分享

图-10

技术分享

图-11

5.2 方案

首先创建Xcode项目,在TRViewController类中定义一个UIImageView类型的属性imageView。然后在viewDidLoad方法中创建一个UIImageView对象imageView添加到父视图中,并根据父视图的宽高比计算出imageView的宽高,将imageView放置在父视图的中间。将属性imageView指向该对象。

其次将imageView的用户交互功能打开,然后在viewDidLoad方法中创建一个旋转手势rotationGR,将手势的响应方法命名为rotate:,最后将旋转手势添加到imageView上。

rotate:方法中通过CGAffineTransformRotate函数改变imageView的transform属性,实现imageView旋转的功能。

然后在viewDidLoad方法中创建一个缩放手势pinchGR,将手势的响应方法命名为pinch:,最后将缩放手势添加到imageView上。

pinch:方法中通过CGAffineTransformScale函数改变imageView的transform属性,实现imageView缩放的功能。

默认情况下,视图在同一时刻只能识别一种手势。如果想要同时识别多种手势就需要给手势指定委托,让手势对象之间进行通信协商两个手势是否能够一起工作。

本案例中旋转手势和缩放手势是可以一起工作的,所以将rotationGR和pinchGR的delegate赋值为TRViewController,TRViewController通过实现协议方法shouldRecognizeSimultaneouslyWithGestureRecognizer:使两个手势能够同时被识别。

最后再创建一个拖拽手势和双击手势添加到imageView上,分别实现拖拽手势和双击手势的响应方法。

5.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建imageView对象

在TRViewController类中定义一个UIImageView类型的属性imageView。然后在viewDidLoad方法中创建一个UIImageView对象imageView添加到父视图中,并根据父视图的宽高比计算出imageView的宽高,将imageView放置在父视图的中间。将属性imageView指向该对象,代码如下所示:

 
  1. //根据父视图宽高计算imageView的宽高
  2. - (void)relocation
  3. {
  4. float horizontalScale = self.view.bounds.size.width / self.imageView.bounds.size.width;
  5. float verticalScale = self.view.bounds.size.height / self.imageView.bounds.size.height;
  6. float realScale = horizontalScale < verticalScale ? horizontalScale:verticalScale;
  7. self.imageView.transform = CGAffineTransformMakeScale(realScale, realScale);
  8. }
  9. //创建imageView对象
  10. - (void)viewDidLoad
  11. {
  12. [super viewDidLoad];
  13.     UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Elephant.jpg"]];
  14. self.imageView = imageView;
  15. [self.view addSubview:imageView];
  16. imageView.center = self.view.center;
  17. [self relocation];
  18. }

步骤二:创建旋转手势,添加到imageView

首先将imageView的用户交互功能打开,然后在viewDidLoad方法中创建一个旋转手势rotationGR,将手势的响应方法命名为rotate:,最后将旋转手势添加到imageView上,代码如下所示:

  1. //打开imageView的交互功能
  2. imageView.userInteractionEnabled = YES;
  3. //创建旋转手势
  4. UIRotationGestureRecognizer *rotationGR = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotate:)];
  5. [imageView addGestureRecognizer:rotationGR];

实现rotate:方法,在该方法中通过CGAffineTransformRotate函数改变imageView的transform属性,实现imageView旋转的功能,代码如下所示:

  1. - (void)rotate:(UIRotationGestureRecognizer *)gr
  2. {
  3. self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, gr.rotation);
  4. gr.rotation = 0;
  5. }

步骤三:创建缩放手势,添加到imageView

首先在viewDidLoad方法中创建一个缩放手势pinchGR,将手势的响应方法命名为pinch:,再将缩放手势添加到imageView上,代码如下所示:

 
  1. UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
  2. [imageView addGestureRecognizer:pinchGR];

然后实现pinch:方法,在该方法中通过CGAffineTransformScale函数改变imageView的transform属性,实现imageView缩放的功能,代码如下所示:

  1. - (void)pinch:(UIPinchGestureRecognizer *)gr
  2. {
  3. self.imageView.transform = CGAffineTransformScale(self.imageView.transform, gr.scale, gr.scale);
  4. gr.scale = 1;
  5. }

步骤四:使旋转和缩放手势能够同时被识别

首先在viewDidLoad方法中将rotationGR和pinchGR的delegate属性赋值为当前视图控制器即TRViewController,代码如下所示:

 
  1. //通过委托,让rotation和pinch可以同时被识别
  2. rotationGR.delegate = self;
  3. pinchGR.delegate = self;

然后在TRViewController类中通过实现协议方法shouldRecognizeSimultaneouslyWithGestureRecognizer:,使两个手势能够同时被识别,代码如下所示:

 
  1. //两个手势对象是否可以同时识别
  2. -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
  3. shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
  4. {
  5. if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class] ]&& [otherGestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
  6. return YES;
  7. }else if([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]&&[otherGestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]]){
  8. return YES;
  9. }
  10. return NO;
  11. }

步骤五:创建拖拽手势和双击手势

首先在viewDidLoad方法中创建一个拖拽手势panGR,将手势的响应方法命名为pan:,然后将缩放手势添加到imageView上,代码如下所示:

 
  1. UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  2. [imageView addGestureRecognizer:panGR];

然后实现pan:方法,该方法中通过CGAffineTransformTranslate函数改变imageView的transform属性,实现imageView的位移功能,代码如下所示:

再创建一个双击手势tapGR,将手势的响应方法命名为tap:,然后将缩放手势添加到imageView上,代码如下所示:

  1. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
  2. tapGR.numberOfTapsRequired = 2;
  3. [imageView addGestureRecognizer:tapGR];

最后实现tap:方法,双击imageView则将imageView置为最初的状态。所示tap:方法中直接调用relocation方法即可,代码如下所示:

 
  1. - (void)tap:(UITapGestureRecognizer *)gr
  2. {
  3. [self relocation];
  4. }

5.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController () <UIGestureRecognizerDelegate>
  3. @property (strong, nonatomic) UIImageView *imageView;
  4. @end
  5. @implementation TRViewController
  6. - (void)viewDidLoad
  7. {
  8. [super viewDidLoad];
  9.     UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Elephant.jpg"]];
  10. self.imageView = imageView;
  11. [self.view addSubview:imageView];
  12. imageView.center = self.view.center;
  13. [self relocation];
  14. //打开用户交互
  15. imageView.userInteractionEnabled = YES;
  16. //添加旋转手势
  17. UIRotationGestureRecognizer *rotationGR = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotate:)];
  18. [imageView addGestureRecognizer:rotationGR];
  19. //添加缩放手势
  20. UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
  21. [imageView addGestureRecognizer:pinchGR];
  22. //添加拖拽手势
  23. UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  24. [imageView addGestureRecognizer:panGR];
  25. //添加双击手势
  26. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
  27. tapGR.numberOfTapsRequired = 2;
  28. [imageView addGestureRecognizer:tapGR];
  29. //通过委托,让rotation和pinch可以同时被识别
  30. rotationGR.delegate = self;
  31. pinchGR.delegate = self;
  32. }
  33. - (void)rotate:(UIRotationGestureRecognizer *)gr
  34. {
  35. self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, gr.rotation);
  36. gr.rotation = 0;
  37. }
  38. - (void)pinch:(UIPinchGestureRecognizer *)gr
  39. {
  40. self.imageView.transform = CGAffineTransformScale(self.imageView.transform, gr.scale, gr.scale);
  41. gr.scale = 1;
  42. }
  43. - (void)pan:(UIPanGestureRecognizer *)gr
  44. {
  45. CGPoint p = [gr translationInView:self.imageView];
  46. self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, p.x, p.y);
  47. [gr setTranslation:CGPointZero inView:self.imageView];
  48. }
  49. - (void)tap:(UITapGestureRecognizer *)gr
  50. {
  51. [self relocation];
  52. }
  53. - (void)relocation
  54. {
  55. float horizontalScale = self.view.bounds.size.width / self.imageView.bounds.size.width;
  56. float verticalScale = self.view.bounds.size.height / self.imageView.bounds.size.height;
  57. float realScale = horizontalScale < verticalScale ? horizontalScale:verticalScale;
  58. self.imageView.transform = CGAffineTransformMakeScale(realScale, realScale);
  59. }
  60. #pragma mark - UIGestureRecognizerDelegate
  61. //两个手势对象是否可以同时识别
  62. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
  63. {
  64. if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class] ]&& [otherGestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
  65. return YES;
  66. }else if([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]&&[otherGestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]]){
  67. return YES;
  68. }
  69. return NO;
  70. }
  71. @end
 

6 演示坐标系四个成员之间的关系

6.1 问题

本案例直接在上一个案例的基础之上增加两个Label查看frame、bounds以及transform之间的关系,如图-12所示:

技术分享

图-12

6.2 方案

首先在上一个案例的界面上添加两个UILabel控件frameLabel和boundslabel,分别用于显示imageView的frame和bounds值。

然后为了观察frame、bounds根据变形产生的变化,在各个手势方法中添加一个用于实时显示imageView的frame和bounds的方法trace。运行程序,可以看出frame会随着transform的变化而变化,bounds始终保持不变。

最后在imageView的右上角75%的位置上添加一个UILable类型的子视图。

6.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:在界面上添加frameLabel和boundslabel

首先在上一个案例的界面上添加两个UILabel控件frameLabel和boundslabel,分别用于显示imageView的frame和bounds值,代码如下所示:

 
  1. UILabel *frameLabel = [[UILabel alloc]init];
  2. self.frameLabel = frameLabel;
  3. frameLabel.frame = CGRectMake(10, 30, 300, 30);
  4. frameLabel.font = [UIFont italicSystemFontOfSize:20];
  5. frameLabel.textColor = [UIColor redColor];
  6. frameLabel.backgroundColor = [UIColor clearColor];
  7. frameLabel.shadowColor = [UIColor greenColor];
  8. frameLabel.shadowOffset = CGSizeMake(1, 1);
  9. frameLabel.text = @"Frame";
  10. [self.view addSubview:frameLabel];
  11. UILabel *boundsLabel = [[UILabel alloc]init];
  12. self.boundsLabel = boundsLabel;
  13. boundsLabel.frame = CGRectMake(10, 70, 300, 30);
  14. boundsLabel.font = [UIFont italicSystemFontOfSize:20];
  15. boundsLabel.textColor = [UIColor redColor];
  16. boundsLabel.backgroundColor = [UIColor clearColor];
  17. boundsLabel.shadowColor = [UIColor greenColor];
  18. boundsLabel.shadowOffset = CGSizeMake(1, 1);
  19. boundsLabel.text = @"Bounds";
  20. [self.view addSubview:boundsLabel];

步骤二:实现trace方法

为了观察frame、bounds根据变形产生的变化,在各个手势方法中添加一个用于实时显示imageView的frame和bounds的方法trace,代码如下所示:

 
  1. - (void)trace
  2. {
  3. self.frameLabel.text = [NSString stringWithFormat:@"%.2f, %.2f, %.2f, %.2f", self.imageView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width, self.imageView.frame.size.height];
  4. self.boundsLabel.text = [NSString stringWithFormat:@"%.2f, %.2f, %.2f, %.2f", self.imageView.bounds.origin.x, self.imageView.bounds.origin.y, self.imageView.bounds.size.width, self.imageView.bounds.size.height];
  5. }

然后运行程序,可以看出frame会随着transform的变化而变化,而bounds始终保持不变。

步骤三:在imageView的右上角子视图label

在imageView的右上角75%的位置上添加一个UILable类型的子视图label。此时label的frame需要根据imageView的bounds来进行计算,而不是imageView的frame,代码如下所示:

 
  1. UILabel *label = [[UILabel alloc]init];
  2. label.backgroundColor = [UIColor redColor];
  3. CGRect frame = CGRectMake(imageView.bounds.size.width * 0.75, imageView.bounds.size.height * 0.25, 200, 200);
  4. label.frame = frame;
  5. [imageView addSubview:label];

6.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController () <UIGestureRecognizerDelegate>
  3. @property (strong, nonatomic) UIImageView *imageView;
  4. @property (strong, nonatomic) UILabel *frameLabel;
  5. @property (strong, nonatomic) UILabel *boundsLabel;
  6. @end
  7. @implementation TRViewController
  8. - (void)relocation
  9. {
  10. float horizontalScale = self.view.bounds.size.width / self.imageView.bounds.size.width;
  11. float verticalScale = self.view.bounds.size.height / self.imageView.bounds.size.height;
  12. float realScale = horizontalScale < verticalScale ? horizontalScale:verticalScale;
  13. self.imageView.transform = CGAffineTransformMakeScale(realScale, realScale);
  14. }
  15. - (void)trace
  16. {
  17. self.frameLabel.text = [NSString stringWithFormat:@"%.2f, %.2f, %.2f, %.2f", self.imageView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width, self.imageView.frame.size.height];
  18. self.boundsLabel.text = [NSString stringWithFormat:@"%.2f, %.2f, %.2f, %.2f", self.imageView.bounds.origin.x, self.imageView.bounds.origin.y, self.imageView.bounds.size.width, self.imageView.bounds.size.height];
  19. }
  20. - (void)viewDidLoad
  21. {
  22. [super viewDidLoad];
  23. //屏幕上增加两行显示imageView的frame和bounds的Label
  24. UILabel *frameLabel = [[UILabel alloc]init];
  25. self.frameLabel = frameLabel;
  26. frameLabel.frame = CGRectMake(10, 30, 300, 30);
  27. frameLabel.font = [UIFont italicSystemFontOfSize:20];
  28. frameLabel.textColor = [UIColor redColor];
  29. frameLabel.backgroundColor = [UIColor clearColor];
  30. frameLabel.shadowColor = [UIColor greenColor];
  31. frameLabel.shadowOffset = CGSizeMake(1, 1);
  32. frameLabel.text = @"Frame";
  33. [self.view addSubview:frameLabel];
  34. UILabel *boundsLabel = [[UILabel alloc]init];
  35. self.boundsLabel = boundsLabel;
  36. boundsLabel.frame = CGRectMake(10, 70, 300, 30);
  37. boundsLabel.font = [UIFont italicSystemFontOfSize:20];
  38. boundsLabel.textColor = [UIColor redColor];
  39. boundsLabel.backgroundColor = [UIColor clearColor];
  40. boundsLabel.shadowColor = [UIColor greenColor];
  41. boundsLabel.shadowOffset = CGSizeMake(1, 1);
  42. boundsLabel.text = @"Bounds";
  43. [self.view addSubview:boundsLabel];
  44.     UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Elephant.jpg"]];
  45. self.imageView = imageView;
  46. [self.view insertSubview:imageView atIndex:0];
  47. imageView.center = self.view.center;
  48. [self relocation];
  49. [self trace];
  50. imageView.userInteractionEnabled = YES;//打开用户交互
  51. UIRotationGestureRecognizer *rotationGR = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotate:)];
  52. [imageView addGestureRecognizer:rotationGR];
  53. UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
  54. [imageView addGestureRecognizer:pinchGR];
  55. UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
  56. [imageView addGestureRecognizer:panGR];
  57. //7.
  58. UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
  59. tapGR.numberOfTapsRequired = 2;
  60. [imageView addGestureRecognizer:tapGR];
  61. //8. 让rotation和pinch可以同时被识别
  62. rotationGR.delegate = self;
  63. pinchGR.delegate = self;
  64. //将一个子视图加入到imageView中的右上角75%的位置
  65. UILabel *label = [[UILabel alloc]init];
  66. label.backgroundColor = [UIColor redColor];
  67. CGRect frame = CGRectMake(imageView.bounds.size.width * 0.75, imageView.bounds.size.height * 0.25, 200, 200);
  68. label.frame = frame;
  69. [imageView addSubview:label];
  70. }
  71. - (void)rotate:(UIRotationGestureRecognizer *)gr
  72. {
  73. self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, gr.rotation);
  74. gr.rotation = 0;
  75. [self trace];
  76. }
  77. - (void)pinch:(UIPinchGestureRecognizer *)gr
  78. {
  79. self.imageView.transform = CGAffineTransformScale(self.imageView.transform, gr.scale, gr.scale);
  80. gr.scale = 1;
  81. [self trace];
  82. }
  83. - (void)pan:(UIPanGestureRecognizer *)gr
  84. {
  85. CGPoint p = [gr translationInView:self.imageView];
  86. self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, p.x, p.y);
  87. [gr setTranslation:CGPointZero inView:self.imageView];
  88. [self trace];
  89. }
  90. - (void)tap:(UITapGestureRecognizer *)gr
  91. {
  92. [self relocation];
  93. }
  94. #pragma mark - UIGestureRecognizerDelegate
  95. //两个手势对象是否可以同时识别
  96. - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
  97. {
  98. if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class] ]&& [otherGestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
  99. return YES;
  100. }else if([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]&&[otherGestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]]){
  101. return YES;
  102. }
  103. return NO;
  104. }
  105. @end
 

手势与变形 、 视图与坐标系

标签:

原文地址:http://www.cnblogs.com/52190112cn/p/5049437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!