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!