UIView继承于UIResponder是一种响应者类,可以响应用户触摸事件。
UIViewController也是继承于UIResponder,属于响应者类。
UIKit 继承链:
UIResponder响应者类提供了便利的方法来处理触摸事件:
UITouch方法:
// 触摸开始
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; // 触摸移动 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; // 触摸结束 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; // 触摸取消 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
有时需要用户触摸某个视图移动,并且视图会跟着触摸手势轨迹的移动的时候,我们可通过触摸移动方法touchesMoved实现。
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"%@", NSStringFromSelector(_cmd));
UITouch *touch = [touches anyObject];
if (touch.view == _showView) {
// 前一个点
CGPoint previousLocation = [touch previousLocationInView:_showView];
// 当前点
CGPoint currentLocation = [touch locationInView:_showView];
// 偏移
CGPoint offset = CGPointMake(currentLocation.x - previousLocation.x,currentLocation.y - previousLocation.y);
// 改变视图位置
_showView.center = CGPointMake(_showView.center.x + offset.x,_showView.center.y + offset.y);
}
}
Cocoa Touch中为我们提供了便利的手势处理类:UIGestureRecognizer
由UIGestureRecognizer衍生的常用子类有:
点击手势:UITapGestureRecognizer
缩放手势:UIPinchGestureRecognizer
旋转手势:UIRotationGestureRecognizer
滑动手势:UISwipeGestureRecognizer
拖动手势:UIPanGestureRecognizer
长按手势:UILongPressGestureRecognizer
初始化手势:
- (id)initWithTarget:(id)target action:(SEL)action;
// 添加手势
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer; // 移除手势 - (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer;
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
#import "UIGestureRecognizerViewController.h"
#define vc_title @"Gesture"
@interface UIGestureRecognizerViewController ()
@property (nonatomic, strong)UILabel *stateLabel;
@property (nonatomic, strong)UIView *gestureView;
/** * 初始化用户界面 */
- (void)initializeUserInterface;
/** * 初始化手势 */
- (void)initializeGestureRecognizer;
@end
@implementation UIGestureRecognizerViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeUserInterface];
[self initializeGestureRecognizer];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// autolayout自动布局
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_stateLabel]-0-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_stateLabel)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[_stateLabel(==30)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_stateLabel)]];
}
#pragma mark - init
- (void)initializeUserInterface
{
self.view.backgroundColor = [UIColor whiteColor];
self.title = vc_title;
[self.view addSubview:self.stateLabel];
[self.view addSubview:self.gestureView];
}
- (void)initializeGestureRecognizer
{
// 1、点击手势识别器
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGestureRecognizer:)];
// 设置点击次数
tapGesture.numberOfTapsRequired = 1;
// 设置手指数量
tapGesture.numberOfTouchesRequired = 1;
// 添加手势
[_gestureView addGestureRecognizer:tapGesture];
// 2、长按手势识别器
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGestureRecognizer:)];
[_gestureView addGestureRecognizer:longPressGesture];
// 3、滑动手势识别器
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGestureRecognizer:)];
// 设置滑动方向:right、left、up、down
swipeGesture.direction = UISwipeGestureRecognizerDirectionRight;
[_gestureView addGestureRecognizer:swipeGesture];
// 4、拖拽手势识别器
UIPanGestureRecognizer *panPress = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGestureRecognizer:)];
[_gestureView addGestureRecognizer:panPress];
// 5、捏合手势识别器
UIPinchGestureRecognizer * pinchPress = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(respondsToGestureRecognizer:)];
[_gestureView addGestureRecognizer:pinchPress];
// 6、旋转手势识别器
UIRotationGestureRecognizer * rotationPress = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(respondsToGestureRecognizer:)];
[_gestureView addGestureRecognizer:rotationPress];
// 手势识别器冲突
[swipeGesture requireGestureRecognizerToFail:panPress]; // 如果冲突,执行后面的
}
#pragma mark - responds event
- (void)respondsToGestureRecognizer:(UIGestureRecognizer *)gesture
{
// 点击手势识别器
if ([gesture isKindOfClass:[UITapGestureRecognizer class]]) {
UITapGestureRecognizer *tap = (UITapGestureRecognizer *)gesture;
// state 属性:获取用户手势状态
if (tap.state == UIGestureRecognizerStateBegan) {
[_stateLabel setText:@"用户开始点击"];
}else if (tap.state == UIGestureRecognizerStateEnded){
[_stateLabel setText:@"用户点击结束"];
}
}
// 长按手势识别器
else if ([gesture isKindOfClass:[UILongPressGestureRecognizer class]]){
UILongPressGestureRecognizer *longPress = (UILongPressGestureRecognizer *)gesture;
if (longPress.state == UIGestureRecognizerStateBegan) {
[_stateLabel setText:@"长按手势开始"];
}else if (longPress.state == UIGestureRecognizerStateEnded){
[_stateLabel setText:@"长按手势结束"];
}
}
// 滑动手势识别器
else if ([gesture isKindOfClass:[UISwipeGestureRecognizer class]]){
UISwipeGestureRecognizer *swipePress = (UISwipeGestureRecognizer *)gesture;
if (swipePress.state == UIGestureRecognizerStateBegan) {
[_stateLabel setText:@"滑动手势开始"];
}else if(swipePress.state == UIGestureRecognizerStateChanged){
[_stateLabel setText:@"滑动手势滑动中"];
}else if (swipePress.state == UIGestureRecognizerStateEnded){
[_stateLabel setText:@"滑动手势结束"];
}
}
// 拖拽手势识别器
else if ([gesture isKindOfClass:[UIPanGestureRecognizer class]]){
UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gesture;
// 声明一个静态的变量记录拖拽视图前时的中心点
static CGPoint firstCenter;
if (pan.state == UIGestureRecognizerStateBegan) {
// 给firstCenter赋值
firstCenter = self.view.center;
[_stateLabel setText:@"拖拽手势开始"];
}else if (pan.state == UIGestureRecognizerStateChanged){
// 获取手势在某一个视图上的移动了多少
CGPoint translation = [pan translationInView:self.view];
_gestureView.center = CGPointMake(firstCenter.x + translation.x, firstCenter.y + translation.y);
[_stateLabel setText:@"拖拽手势拖动中"];
}else if (pan.state == UIGestureRecognizerStateEnded){
// 更新静态变量firstCenter的值,供下次识别这个手势时使用
firstCenter = _gestureView.center;
[_stateLabel setText:@"拖拽手势结束"];
}
}
// 捏合手势识别器
else if ([gesture isKindOfClass:[UIPinchGestureRecognizer class]]){
UIPinchGestureRecognizer * pinch = (UIPinchGestureRecognizer *)gesture;
static CGFloat lastScale;
if (pinch.state == UIGestureRecognizerStateBegan) {
lastScale = pinch.scale;
[_stateLabel setText:@" 捏合手势开始"];
}else if (pinch.state == UIGestureRecognizerStateChanged){
CGFloat changeScale = (pinch.scale - lastScale)/2 + 1;
if (_gestureView.bounds.size.width < 100) { // 当视图<100,就不能再缩小
return;
}else{
_gestureView.transform = CGAffineTransformScale(_gestureView.transform, changeScale, changeScale);
lastScale = pinch.scale;
}
}else if (pinch.state == UIGestureRecognizerStateEnded){
lastScale = 1;
[_stateLabel setText:@" 捏合手势结束"];
}
}
// 旋转手势识别器
else if ([gesture isKindOfClass:[UIRotationGestureRecognizer class]]){
UIRotationGestureRecognizer * rotation = (UIRotationGestureRecognizer *)gesture;
static CGFloat lastRotate;
if (rotation.state == UIGestureRecognizerStateBegan) {
lastRotate = rotation.rotation;
[_stateLabel setText:@"旋转手势开始"];
}else if (rotation.state == UIGestureRecognizerStateChanged){
CGFloat changeRotate = rotation.rotation - lastRotate;
_gestureView.transform = CGAffineTransformRotate(_gestureView.transform, changeRotate);
lastRotate = rotation.rotation;
}else if(rotation.state){
lastRotate = 0;
}
}
}
#pragma mark - getter
- (UILabel *)stateLabel
{
if (!_stateLabel) {
_stateLabel = [[UILabel alloc] init];
_stateLabel.translatesAutoresizingMaskIntoConstraints = NO;
_stateLabel.textAlignment = NSTextAlignmentCenter;
_stateLabel.font = [UIFont systemFontOfSize:25];
}
return _stateLabel;
}
- (UIView *)gestureView
{
if (!_gestureView) {
_gestureView = [[UIView alloc] init];
_gestureView.bounds = CGRectMake(0, 0, 200, 200);
_gestureView.center = self.view.center;
_gestureView.backgroundColor = [UIColor redColor];
// 开启用户交互
_gestureView.userInteractionEnabled = YES;
}
return _gestureView;
}
@end