前言
· UIView是我们在开发中经常使用到的控件,很多时候需要在该控件上面添加手势处理。常规的做法就是实例手势然后添加,程序员都是很懒的,并且我也一直比较喜欢东西都放在一起查找起来也方便。常规的声明和处理分开在代码量巨大的情形之下找起来还是略显麻烦,所以我将手势封装一下,方便使用
API
NS_ASSUME_NONNULL_BEGIN typedef void(^KJGestureRecognizerBlock)(UIView *view, UIGestureRecognizer *gesture); typedef NS_ENUM(NSUInteger, KJGestureType) { KJGestureTypeTap, // 点击 KJGestureTypeDouble, // 双击 KJGestureTypeLongPress, // 长按 KJGestureTypeSwipe, // 轻扫 KJGestureTypePan, // 移动 KJGestureTypeRotate, // 旋转 KJGestureTypePinch, // 缩放 }; static NSString * const _Nonnull KJGestureTypeStringMap[] = { [KJGestureTypeTap] = @"UITapGestureRecognizer", [KJGestureTypeDouble] = @"UITapGestureRecognizer", [KJGestureTypeLongPress] = @"UILongPressGestureRecognizer", [KJGestureTypeSwipe] = @"UISwipeGestureRecognizer", [KJGestureTypePan] = @"UIPanGestureRecognizer", [KJGestureTypeRotate] = @"UIRotationGestureRecognizer", [KJGestureTypePinch] = @"UIPinchGestureRecognizer", }; @interface UIView (KJGestureBlock) /// 单击手势 - (UIGestureRecognizer*)kj_AddTapGestureRecognizerBlock:(KJGestureRecognizerBlock)block; /// 手势处理 - (UIGestureRecognizer*)kj_AddGestureRecognizer:(KJGestureType)type block:(KJGestureRecognizerBlock)block; @end NS_ASSUME_NONNULL_END
使用示例
_weakself; [self.displayImageView kj_AddTapGestureRecognizerBlock:^(UIView * _Nonnull view, UIGestureRecognizer * _Nonnull gesture) { NSLog(@"单击"); }]; [self.displayImageView kj_AddGestureRecognizer:(KJGestureTypeDouble) block:^(UIView * _Nonnull view, UIGestureRecognizer * _Nonnull gesture) { NSLog(@"双击"); }]; [self.displayImageView kj_AddGestureRecognizer:(KJGestureTypePan) block:^(UIView * _Nonnull view, UIGestureRecognizer * _Nonnull gesture) { UIPanGestureRecognizer *panGestureRecognizer = (UIPanGestureRecognizer*)gesture; CGPoint translation = [panGestureRecognizer translationInView:panGestureRecognizer.view]; NSLog(@"移动%.2f",translation.x); }]; [self.displayImageView kj_AddGestureRecognizer:(KJGestureTypePinch) block:^(UIView * _Nonnull view, UIGestureRecognizer * _Nonnull gesture) { UIPinchGestureRecognizer *pinchGestureRecognizer = (UIPinchGestureRecognizer*)gesture; NSLog(@"缩放%.2f,%.2f",weakself.lastScale,pinchGestureRecognizer.scale); switch (pinchGestureRecognizer.state) { case UIGestureRecognizerStateBegan: case UIGestureRecognizerStateChanged:{ CGFloat scale = weakself.lastScale+pinchGestureRecognizer.scale-1; if (scale >= weakself.maxScale || scale <= weakself.minScale) { return; } CGFloat w = kScreenW * scale; CGFloat h = kScreenH * scale; CGFloat x = weakself.originRect.origin.x - (kScreenW*(scale-1))/2.; CGFloat y = weakself.originRect.origin.y - (kScreenH*(scale-1))/2.; view.frame = CGRectMake(x, y, w, h); } break; case UIGestureRecognizerStateEnded:{ CGFloat scale = weakself.lastScale+pinchGestureRecognizer.scale-1; if (scale >= weakself.maxScale) { weakself.lastScale = weakself.maxScale; }else if (scale <= weakself.minScale) { weakself.lastScale = weakself.minScale; }else{ weakself.lastScale += (pinchGestureRecognizer.scale-1); } } break; default: break; } }];
简单介绍
1. 开启视图的交换
外界使用的时候也不需要再写该属性,又省一句代码- -|
self.userInteractionEnabled = YES;
2. 声明和添加
这里提供七种手势枚举
typedef NS_ENUM(NSUInteger, KJGestureType) { KJGestureTypeTap, // 点击 KJGestureTypeDouble, // 双击 KJGestureTypeLongPress, // 长按 KJGestureTypeSwipe, // 轻扫 KJGestureTypePan, // 移动 KJGestureTypeRotate, // 旋转 KJGestureTypePinch, // 缩放 }; static NSString * const _Nonnull KJGestureTypeStringMap[] = { [KJGestureTypeTap] = @"UITapGestureRecognizer", [KJGestureTypeDouble] = @"UITapGestureRecognizer", [KJGestureTypeLongPress] = @"UILongPressGestureRecognizer", [KJGestureTypeSwipe] = @"UISwipeGestureRecognizer", [KJGestureTypePan] = @"UIPanGestureRecognizer", [KJGestureTypeRotate] = @"UIRotationGestureRecognizer", [KJGestureTypePinch] = @"UIPinchGestureRecognizer", };
NSClassFromString得到对应的手势类
NSString *string = KJGestureTypeStringMap[type]; __block UIGestureRecognizer *gesture = [[NSClassFromString(string) alloc] initWithTarget:self action:@selector(kGestureAction:)]; [gesture setDelaysTouchesBegan:YES]; [self addGestureRecognizer:gesture];
3. 解决单击和双击共存问题
if (type == KJGestureTypeTap) { [self.gestureRecognizers enumerateObjectsUsingBlock:^(__kindof UIGestureRecognizer *recognizer, NSUInteger idx, BOOL *stop) { if ([recognizer isKindOfClass:[UITapGestureRecognizer class]] && ((UITapGestureRecognizer*)recognizer).numberOfTapsRequired == 2) { [gesture requireGestureRecognizerToFail:recognizer]; *stop = YES; } }]; string = [string stringByAppendingString:@"Tap"]; }else if (type == KJGestureTypeDouble) { [(UITapGestureRecognizer*)gesture setNumberOfTapsRequired:2]; [self.gestureRecognizers enumerateObjectsUsingBlock:^(__kindof UIGestureRecognizer *recognizer, NSUInteger idx, BOOL *stop) { if ([recognizer isKindOfClass:[UITapGestureRecognizer class]] && ((UITapGestureRecognizer*)recognizer).numberOfTapsRequired == 1) { [recognizer requireGestureRecognizerToFail:gesture]; *stop = YES; } }]; string = [string stringByAppendingString:@"Double"]; }
4. 保存回调
这里增加一个selectorString
属性来区分不同的回调
self.selectorString = string; self.gesrureblock = block;
NSSelectorFromString 得到不同的回调
#pragma mark - associated - (NSString*)selectorString{ return objc_getAssociatedObject(self, @selector(selectorString)); } - (void)setSelectorString:(NSString*)selectorString{ objc_setAssociatedObject(self, @selector(selectorString), selectorString, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (KJGestureRecognizerBlock)gesrureblock{ return (KJGestureRecognizerBlock)objc_getAssociatedObject(self, NSSelectorFromString(self.selectorString)); } - (void)setGesrureblock:(KJGestureRecognizerBlock)gesrureblock{ objc_setAssociatedObject(self, NSSelectorFromString(self.selectorString), gesrureblock, OBJC_ASSOCIATION_COPY_NONATOMIC); }
5. 处理手势
- (void)kGestureAction:(UIGestureRecognizer*)gesture{ NSString *string = NSStringFromClass([gesture class]); if ([gesture isKindOfClass:[UITapGestureRecognizer class]]) { if (((UITapGestureRecognizer*)gesture).numberOfTapsRequired == 1) { string = [string stringByAppendingString:@"Tap"]; }else { string = [string stringByAppendingString:@"Double"]; } } self.selectorString = string; self.gesrureblock(gesture.view, gesture); }