UIScrollView中的手势
UIScrollView中的手势
UIScrollView自带了两个手势,分别为:
UIPanGestureRecognizer
UIPinchGestureRecognizer
他们都是readonly的.
监听UIPanGestureRecognizer
手势是UIPanGestureRecognizer的属性,我们可以使用KVO来进行监听.
#import "RootViewController.h" #define WIDTH self.view.frame.size.width #define HEIGHT self.view.frame.size.height @interface RootViewController ()<UIScrollViewDelegate> @property (nonatomic, strong) UIScrollView *scrollView; @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT)]; _scrollView.contentSize = CGSizeMake(WIDTH, HEIGHT * 3); [self.view addSubview:_scrollView]; [_scrollView addObserver:self forKeyPath:@"panGestureRecognizer.state" options:NSKeyValueObservingOptionNew context:nil]; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // 监听pan手势开始 if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan) { NSLog(@"UIGestureRecognizerStateBegan"); } // 监听pan手势值改变 if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateChanged) { NSLog(@"UIGestureRecognizerStateChanged"); } // 监听pan手势结束 if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) { NSLog(@"UIGestureRecognizerStateEnded"); } } - (void)dealloc { [_scrollView removeObserver:self forKeyPath:@"panGestureRecognizer.state"]; } @end
核心代码如下:
本人在测试的时候发现,一个完整的手势事件,一般情况下,手势值的改变是会执行多次的,而UIScrollview中的pan手势处理过后,手势开始,手势值改变以及手势结束,均只执行一回.
添加UISwipeGestureRecognizer手势
我们可以给UIScrollview添加UISwipeGestureRecognizer手势来判断是往哪个方向轻轻滑动了.
#import "RootViewController.h" #import "GestureView.h" @interface RootViewController ()<UIGestureRecognizerDelegate> @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; #define WIDTH self.view.frame.size.width #define HEIGHT self.view.frame.size.height UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; scrollView.backgroundColor = [UIColor grayColor]; scrollView.contentSize = CGSizeMake(WIDTH, HEIGHT*3); [self.view addSubview:scrollView]; UISwipeGestureRecognizer *up = \ [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeEvent:)]; up.direction = UISwipeGestureRecognizerDirectionUp; up.delegate = self; [scrollView addGestureRecognizer:up]; UISwipeGestureRecognizer *down = \ [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeEvent:)]; down.direction = UISwipeGestureRecognizerDirectionDown; down.delegate = self; [scrollView addGestureRecognizer:down]; } - (void)swipeEvent:(UISwipeGestureRecognizer *)gesture { NSLog(@"%@", gesture); } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } @end
我直接将手势对象添加进category中,运行时关联上手势对象:
UIScrollView+Swipe.h + UIScrollView+Swipe.m
#import <UIKit/UIKit.h> typedef enum { E_UP = 0x1000, E_DOWN, } EDirection; @protocol UIScrollViewSwipeProtocol <NSObject> - (void)swipeDirection:(EDirection)direction; @end @interface UIScrollView (Swipe) @property (nonatomic, assign) id<UIScrollViewSwipeProtocol> swipeProtocol; @property (nonatomic, strong, readonly) UISwipeGestureRecognizer *upGesture; @property (nonatomic, strong, readonly) UISwipeGestureRecognizer *downGesture; - (void)activateSwipeGesture; - (void)cancelSwipeGesture; @end
#import "UIScrollView+Swipe.h" #import <objc/runtime.h> @interface UIScrollView ()<UIGestureRecognizerDelegate> @property (nonatomic, strong, readwrite) UISwipeGestureRecognizer *upGesture; @property (nonatomic, strong, readwrite) UISwipeGestureRecognizer *downGesture; @end static char swipeProtocolFlag; static char upGestureFlag; static char downGestureFlag; @implementation UIScrollView (Swipe) - (id<UIScrollViewSwipeProtocol>)swipeProtocol { return objc_getAssociatedObject(self, &swipeProtocolFlag); } - (void)setSwipeProtocol:(id<UIScrollViewSwipeProtocol>)swipeProtocol { objc_setAssociatedObject(self, &swipeProtocolFlag, swipeProtocol, OBJC_ASSOCIATION_ASSIGN); } - (void)setUpGesture:(UISwipeGestureRecognizer *)upGesture { objc_setAssociatedObject(self, &upGestureFlag, upGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UISwipeGestureRecognizer *)upGesture { return objc_getAssociatedObject(self, &upGestureFlag); } - (void)setDownGesture:(UISwipeGestureRecognizer *)downGesture { objc_setAssociatedObject(self, &downGestureFlag, downGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UISwipeGestureRecognizer *)downGesture { return objc_getAssociatedObject(self, &downGestureFlag); } - (void)activateSwipeGesture { if (self.upGesture == nil) { self.upGesture = \ [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGestureEvents:)]; self.upGesture.direction = UISwipeGestureRecognizerDirectionUp; self.upGesture.delegate = self; [self addGestureRecognizer:self.upGesture]; } if (self.downGesture == nil) { self.downGesture = \ [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGestureEvents:)]; self.downGesture.direction = UISwipeGestureRecognizerDirectionDown; self.downGesture.delegate = self; [self addGestureRecognizer:self.downGesture]; } } - (void)swipeGestureEvents:(UISwipeGestureRecognizer *)gesture { if (self.swipeProtocol) { if (self.downGesture == gesture) { [self.swipeProtocol swipeDirection:E_DOWN]; } if (self.upGesture == gesture) { [self.swipeProtocol swipeDirection:E_UP]; } } } - (void)cancelSwipeGesture { [self removeGestureRecognizer:self.upGesture]; [self removeGestureRecognizer:self.downGesture]; self.upGesture = nil; self.downGesture = nil; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } @end
然后这么使用即可:),so easy!