日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS手势处理

發布時間:2024/9/5 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS手势处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

iOS手勢處理

iOS手勢有著如下幾種:

  • UITapGestureRecognizer??
  • UIPinchGestureRecognizer
  • UIRotationGestureRecognizer
  • UISwipeGestureRecognizer
  • UIPanGestureRecognizer
  • UILongPressGestureRecognizer

上面的手勢對應的操作是:?

  • Tap????????? (點一下)
  • Pinch??????? (二指往內或往外撥動,平時經常用到的縮放)? 矩陣變換
  • Rotation??? (旋轉)????????????????????????????????????????????????? 矩陣變換
  • Swipe?????? (滑動,快速移動)
  • Pan????????? (拖移,慢速移動)???????????????????????????????????? 矩陣變換
  • LongPress (長按

?

注意:以下示例均把手勢封裝進一個View當中

UITapGestureRecognizer - 點擊手勢

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>@interface GestureView : UIView@end GestureView.h #import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UITapGestureRecognizer *tapGesture; @property (nonatomic, strong) CALayer *colorLayer; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {// 初始化手勢,給手勢指定響應事件的對象_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(gestureEvent:)];_colorLayer = [CALayer layer];_colorLayer.frame = self.bounds;[self.layer addSublayer:_colorLayer];// 將手勢與區域綁定 [self addGestureRecognizer:_tapGesture];}return self; }- (void)gestureEvent:(UIGestureRecognizer *)sender {_colorLayer.backgroundColor = [UIColor colorWithRed:arc4random() % 255 / 255.fgreen:arc4random() % 255 / 255.fblue:arc4random() % 255 / 255.falpha:1.0f].CGColor; }@end GestureView.m

- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer

Attaching a gesture recognizer to a view defines the scope of the represented gesture, causing it to receive touches hit-tested to that view and all of its subviews. The view establishes a strong reference to the gesture recognizer.

將手勢識別器附著在一個view上,實際上定義了一個手勢接收的區域,會將接收到的觸摸事件傳遞給這個view以及這個view的所有的subviews.這個view會對這個手勢識別器強引用.

可以總結兩點:

1. 手勢會傳遞給這個view中所有的subviews

2. view會強引用手勢識別器

使用如下:

點擊手勢有兩個參數可以設置:

numberOfTapsRequired???????? 點擊幾次觸發事件(默認是1)

numberOfTouchesRequired??? 需要幾個手指點擊(默認是1)

?

UIPinchGestureRecognizer - 縮放

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>@interface GestureView : UIView@end GestureView.h #import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UIPinchGestureRecognizer *pinchGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self){// 初始化手勢,給手勢指定響應事件的對象_pinchGesture = \[[UIPinchGestureRecognizer alloc] initWithTarget:selfaction:@selector(gestureEvent:)];// 將手勢與區域綁定 [self addGestureRecognizer:_pinchGesture];}return self; }- (void)gestureEvent:(UIPinchGestureRecognizer *)sender {// self.transform = CGAffineTransformScale(self.transform, sender.scale, sender.scale);sender.scale = 1; }@end GestureView.m

縮放手勢會用到矩陣變換.

?

UIRotationGestureRecognizer - 旋轉

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>@interface GestureView : UIView@end GestureView.h #import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UIRotationGestureRecognizer *rotationGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self){// 初始化手勢,給手勢指定響應事件的對象_rotationGesture = \[[UIRotationGestureRecognizer alloc] initWithTarget:selfaction:@selector(gestureEvent:)];// 將手勢與區域綁定 [self addGestureRecognizer:_rotationGesture];}return self; }- (void)gestureEvent:(UIRotationGestureRecognizer *)sender {// 此處用到了矩陣變換self.transform = CGAffineTransformRotate(self.transform, sender.rotation);sender.rotation = 0; } GestureView.m

?

UISwipeGestureRecognizer - 滑動

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>@interface GestureView : UIView@end GestureView.h #import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UISwipeGestureRecognizer *swipeGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self){// 初始化手勢,給手勢指定響應事件的對象_swipeGesture = \[[UISwipeGestureRecognizer alloc] initWithTarget:selfaction:@selector(gestureEvent:)];_swipeGesture.direction = \UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;// 將手勢與區域綁定 [self addGestureRecognizer:_swipeGesture];}return self; }- (void)gestureEvent:(UISwipeGestureRecognizer *)sender {NSLog(@"left or right"); }@end GestureView.m

?

UIPanGestureRecognizer - 平移

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>@interface GestureView : UIView@end GestureView.h #import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UIPanGestureRecognizer *panGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self){// 初始化手勢,給手勢指定響應事件的對象_panGesture = \[[UIPanGestureRecognizer alloc] initWithTarget:selfaction:@selector(gestureEvent:)];// 將手勢與區域綁定 [self addGestureRecognizer:_panGesture];}return self; }- (void)gestureEvent:(UIPanGestureRecognizer *)sender {// 此處用到了矩陣變換CGPoint translation = [sender translationInView:self];self.center = CGPointMake(self.center.x + translation.x,self.center.y + translation.y);[sender setTranslation:CGPointZeroinView:self]; }@end GestureView.m

?

UILongPressGestureRecognizer - 長按手勢

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>@interface GestureView : UIView@end GestureView.h #import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UILongPressGestureRecognizer *longPressGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self){// 初始化手勢,給手勢指定響應事件的對象_longPressGesture = \[[UILongPressGestureRecognizer alloc] initWithTarget:selfaction:@selector(gestureEvent:)];_longPressGesture.minimumPressDuration = 2.0f;// 將手勢與區域綁定 [self addGestureRecognizer:_longPressGesture];}return self; }- (void)gestureEvent:(UILongPressGestureRecognizer *)sender {NSLog(@"觸發事件"); }@end GestureView.m

?

?

問題:如何處理一個view中添加了兩個手勢,1個是單擊的手勢,一個是雙擊的手勢呢?

可以使用這個方法requireGestureRecognizerToFail:

#import "GestureView.h"@interface GestureView () @property (nonatomic, strong) UITapGestureRecognizer *tapGesture1; @property (nonatomic, strong) UITapGestureRecognizer *tapGesture2; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {// 單擊手勢_tapGesture1 = \[[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(gesture1Event:)];_tapGesture1.numberOfTapsRequired = 1;// 雙擊手勢_tapGesture2 = \[[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(gesture2Event:)];_tapGesture2.numberOfTapsRequired = 2;// 注意: 判斷雙擊手勢需要時間,也就是說會有延時// 有事件觸發時,先判斷是不是 雙擊手勢,如果不是就執行 單擊手勢 [_tapGesture1 requireGestureRecognizerToFail:_tapGesture2];// 將手勢與區域綁定 [self addGestureRecognizer:_tapGesture1];[self addGestureRecognizer:_tapGesture2];}return self; }- (void)gesture1Event:(UIGestureRecognizer *)sender {NSLog(@"1"); }- (void)gesture2Event:(UIGestureRecognizer *)sender {NSLog(@"2"); }@end GestureView.m

實際上,這種方式會有延時感-_-!!!!

?

問題:如何將長按手勢和拖拽手勢合并在一起呢??

我們需要用代理實現,實現以下的方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer? shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

Asks the delegate if two gesture recognizers should be allowed to recognize gestures simultaneously.

詢問這個代理,是否允許兩個手勢同時觸發.

#import "GestureView.h"@interface GestureView ()<UIGestureRecognizerDelegate>{BOOL shouldAllowPan; }@property (nonatomic, strong) UIPanGestureRecognizer *panGesture; @property (nonatomic, strong) UILongPressGestureRecognizer *longPressGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {// 初始化時不允許拖拽shouldAllowPan = NO;_panGesture = \[[UIPanGestureRecognizer alloc] initWithTarget:selfaction:@selector(panEvent:)];[self addGestureRecognizer:_panGesture];_panGesture.delegate = self;_longPressGesture = \[[UILongPressGestureRecognizer alloc] initWithTarget:selfaction:@selector(longPressEvent:)];_longPressGesture.minimumPressDuration = 1.0f;[self addGestureRecognizer:_longPressGesture];_longPressGesture.delegate = self;}return self; }- (void)panEvent:(UIPanGestureRecognizer *)sender {if(shouldAllowPan == YES){// 移動的操作CGPoint translation = [sender translationInView:self];self.center = CGPointMake(self.center.x + translation.x,self.center.y + translation.y);[sender setTranslation:CGPointZeroinView:self];}else if(sender.state == UIGestureRecognizerStateEnded || \sender.state == UIGestureRecognizerStateFailed || \sender.state == UIGestureRecognizerStateCancelled){shouldAllowPan = NO;} }- (void)longPressEvent:(UIGestureRecognizer *)sender {// 長按開始if(UIGestureRecognizerStateBegan == sender.state){NSLog(@"長按開始");self.backgroundColor = [UIColor redColor];shouldAllowPan = NO;}// 長按進行中if(UIGestureRecognizerStateChanged == sender.state){NSLog(@"長按進行中");shouldAllowPan = YES;}// 長按結束if(UIGestureRecognizerStateEnded == sender.state){NSLog(@"長按結束");self.backgroundColor = [UIColor blackColor];shouldAllowPan = NO;} }// 是否允許多個手勢同時觸發 - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {// 允許return YES; }// 是否允許繼續跟蹤觸摸事件 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {// 條件滿足的手勢會被傳遞進來(如果是移動手勢,)if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && shouldAllowPan == NO){return NO;}return YES; }@end GestureView.m

根據手勢狀態來識別手勢觸發事件的全稱細節是十分重要的.

?

問題:如何讓一個view的部分區域響應拖拽事件呢?

比方說,我們只需要下面紅色線指定的區域響應拖拽事件:

#import "GestureView.h"@interface GestureView (){BOOL allowPan;}@property (nonatomic, strong) UIPanGestureRecognizer *panGesture; @end@implementation GestureView- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self){// 初始化時不允許拖拽allowPan = NO;_panGesture = \[[UIPanGestureRecognizer alloc] initWithTarget:selfaction:@selector(panEvent:)];[self addGestureRecognizer:_panGesture];}return self; }- (void)panEvent:(UIPanGestureRecognizer *)sender {// 獲取到當前手勢在當前視圖坐標中觸摸的點CGPoint point = [sender locationInView:self];// 手勢開始時置位(手勢事件開始過程中僅僅執行一回)if (sender.state == UIGestureRecognizerStateBegan){// 設定響應的區域if (self.bounds.size.height / 2.f >= point.x && self.bounds.size.width / 2.f >= point.y){allowPan = YES;}}// 手勢持續(手勢事件開始過程中執行多回)if (sender.state == UIGestureRecognizerStateChanged && allowPan == YES){// 移動的操作CGPoint translation = [sender translationInView:self];self.center = CGPointMake(self.center.x + translation.x,self.center.y + translation.y);[sender setTranslation:CGPointZeroinView:self];}// 手勢結束后置位(手勢事件開始過程中僅僅執行一回)if (sender.state == UIGestureRecognizerStateEnded){allowPan = NO;} }@end GestureView.m

?要實現那個效果,以下方法是核心方法,配合手勢的狀態使用:

// 獲取到當前手勢在當前視圖坐標中觸摸的點
??? CGPoint point = [sender locationInView:self];

?

問題:如何在ViewController中獲取到點擊的坐標,讓一個view跟隨觸摸點移動呢?

可以使用這幾個最原始的處理觸摸事件的方法來達到效果.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

#import "RootViewController.h"@interface RootViewController (){UIView *_panPoint;CALayer *_redLayer; }@end@implementation RootViewController- (void)viewDidLoad {[super viewDidLoad];// 初始化view_panPoint = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];_panPoint.layer.cornerRadius = 25.f;_panPoint.layer.masksToBounds = YES;[self.view addSubview:_panPoint];// 初始化一個layer_redLayer = [CALayer layer];_redLayer.frame = _panPoint.bounds;_redLayer.backgroundColor = [UIColor redColor].CGColor;_redLayer.opacity = 0.f;[_panPoint.layer addSublayer:_redLayer]; }// 一次完整的觸摸事件中,touchesBegan只執行一回 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {// 獲取觸摸點坐標UITouch *touch = [touches anyObject];CGPoint touchPoint = [touch locationInView:self.view];_panPoint.center = touchPoint;_redLayer.opacity = 1.0f; }- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {// 獲取觸摸點坐標UITouch *touch = [touches anyObject];CGPoint touchPoint = [touch locationInView:self.view];_panPoint.center = touchPoint; }// 一次完整的觸摸事件中,touchesEnded只執行一回 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {// 獲取觸摸點坐標UITouch *touch = [touches anyObject];CGPoint touchPoint = [touch locationInView:self.view];_panPoint.center = touchPoint;_redLayer.opacity = 0.0f; }@end RootViewController.m

也可以直接使用拖拽手勢來實現的,不過不完美

#import "RootViewController.h"@interface RootViewController (){UIView *_panPoint;CALayer *_redLayer; }@end@implementation RootViewController- (void)viewDidLoad {[super viewDidLoad];// 初始化view_panPoint = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];_panPoint.layer.cornerRadius = 25.f;_panPoint.layer.masksToBounds = YES;[self.view addSubview:_panPoint];// 初始化一個layer_redLayer = [CALayer layer];_redLayer.frame = _panPoint.bounds;_redLayer.backgroundColor = [UIColor redColor].CGColor;_redLayer.opacity = 0.f;[_panPoint.layer addSublayer:_redLayer];// 定義手勢UIPanGestureRecognizer *panGesture = \[[UIPanGestureRecognizer alloc] initWithTarget:selfaction:@selector(panGestureEvent:)];[self.view addGestureRecognizer:panGesture]; }- (void)panGestureEvent:(UIPanGestureRecognizer *)sender {CGPoint touchPoint = [sender locationInView:self.view];if (sender.state == UIGestureRecognizerStateBegan){_panPoint.center = touchPoint;_redLayer.opacity = 1.0f;}else if (sender.state == UIGestureRecognizerStateChanged){_panPoint.center = touchPoint;}else if (sender.state == UIGestureRecognizerStateEnded){_panPoint.center = touchPoint;_redLayer.opacity = 0.0f;} }@end RootViewController.m

他們兩者的對比關系:

?

?

手勢處理中核心的地方:

1.? UIGestureRecognizerState非常重要,觸發事件時可以直接根據這個狀態值來判斷事件的發生順序

2.? 處理多手勢沖突時,可以使用依賴requireGestureRecognizerToFail:來處理,但效果不好

3.? 處理多個手勢并發響應的時候,需要實現代理并執行方法,請參考上面的事例

4.? 僅僅處理一個view上局部的手勢事件,需要用到手勢的locationInView:方法,并與UIGestureRecognizerState狀態值配合使用

?

?

附錄:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch

這是手勢的代理方法,在可以不移除手勢的情況下關閉手勢的響應,此方法涉及到響應鏈.

?

轉載于:https://www.cnblogs.com/YouXianMing/p/3715456.html

總結

以上是生活随笔為你收集整理的iOS手势处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。