iOS_38_手势

Pan平移手势
最终效果图:

Swipe轻扫手势


LongPress长按手势



Pinch和Rotation手势


捏合(缩放)和旋转


最终效果图:



涂鸦

最终效果图:


iOS_38_手势_第1张图片

事件分3大类:触摸、加速计、远程遥控

只有响应者的子类,才可以接收和处理事件
iOS_38_手势_第2张图片
父类响应者中定义的事件处理接口如下:
iOS_38_手势_第3张图片
触摸事件处理的四个方法如下:(只要实现,系统会自动调用)
iOS_38_手势_第4张图片
一个UITouch对象,代表着一根手指,手指移动,UITouch对象实时更新

一个UITouch对象,对应一根手指,记录着触摸时的所有信息
iOS_38_手势_第5张图片
重要~经常使用UITouch的方法,取得触摸时的信息(如位置、所点对象)
iOS_38_手势_第6张图片
事件对象UIEvent,常用的属性是:事件类型
iOS_38_手势_第7张图片
触摸的四个方法(即过程)详解:注意同时和一前一后触摸的情况
iOS_38_手势_第8张图片
必须先找到事件的最合适的响应者(从父到子地找)
iOS_38_手势_第9张图片
下面是寻找最合适的事件响应者具体例子:
iOS_38_手势_第10张图片
特殊情况:要尤其注意

找到了事件的最佳处理者之后,就是响应者链条了
默认是会调用其[super touchesXXX],这个super就是上一个响应者
即:官方文档中的next responder

下面是官方文档中关于上一个响应者的图片,即Next Responder
iOS_38_手势_第11张图片
总结起来就是:view有控制器,则传给控制器;否则,传给父view
iOS_38_手势_第12张图片
再次总结:响应者链条传递机制(上一个响应者就是NEXT RESPONDER)

传统监听事件的做法:(不再推荐使用)
iOS_38_手势_第13张图片
六种手势识别器,后面会具体举例:
如果要同时监听两种以上的手势:
为每一个手势设置delegate,并且实现下面的方法

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



手势识别器的标准做法:三步曲(创建、设置、绑定)
iOS_38_手势_第14张图片
重点关注三种手势识别的状态:开始\结束\取消
iOS_38_手势_第15张图片
官方文档中关于手势识别的状态变化图
iOS_38_手势_第16张图片
手势识别器的代理方法< UIGestureRecognizerDelegate>
其中:shouldReceiveTouch可以指定手势在特定条件下有效

shouldRecognizeSimultaneouslyWithGestureRecognizer

返回YES代表可以同时识别不同手势,如同时旋转和缩放



Pan平移手势
最终效果图:

//
//  PanController.m
//  38_手势
//
//  Created by beyond on 14-9-16.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "PanController.h"

@interface PanController ()
// nana头像所在的View
@property (weak, nonatomic) IBOutlet UIView *nanaView;
- (IBAction)dismiss;

@end

@implementation PanController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 创建pan手势,并绑定监听方法
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panView:)];
    [self.nanaView addGestureRecognizer:pan];
}

- (void)panView:(UIPanGestureRecognizer *)pan
{
    
    switch (pan.state) {
        case UIGestureRecognizerStateBegan: // 开始触发手势
            
            break;
            
        case UIGestureRecognizerStateEnded: // 手势结束
            
            break;
            
        default:
            break;
    }
    
    // 1.在view上面挪动的距离
    CGPoint translation = [pan translationInView:pan.view];
    CGPoint center = pan.view.center;
    center.x += translation.x;
    center.y += translation.y;
    pan.view.center = center;
    
    // 2.清空移动的距离
    [pan setTranslation:CGPointZero inView:pan.view];
}

#pragma mark - 连线
- (IBAction)dismiss
{
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end


Tap手势
//
//  TapController.m
//  38_手势
//
//  Created by beyond on 14-9-16.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "TapController.h"

// 手势代理
@interface TapController ()<UIGestureRecognizerDelegate>

@property (weak, nonatomic) IBOutlet UIImageView *nanaImgView;

- (IBAction)dismiss;

@end

@implementation TapController

- (void)viewDidLoad
{
    [super viewDidLoad];
    _nanaImgView.userInteractionEnabled = YES;
    _nanaImgView.multipleTouchEnabled = YES;
    //[self testTap];
    [self testTap2];
}

- (void)testTap
{
    // 1.创建Tap手势识别器对象
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
    // 两根手势,连续敲击2次,手势才能识别成功
    tap.numberOfTapsRequired = 2;
    tap.numberOfTouchesRequired = 2;
    
    // 2.添加监听方法(识别到了对应的手势,就会调用监听方法)
    [tap addTarget:self action:@selector(taping)];
    
    // 3.为nanaImgView 添加Tap手势识别器对象
    [self.nanaImgView addGestureRecognizer:tap];
}

- (void)testTap2
{
    // 1.创建Tap手势识别器对象,同时绑定监听方法(识别到了对应的手势,就会调用监听方法)
    UIGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(taping)];
    // 2.设置手势的代理,目的是:决定手势只有在特定场合才会被识别(触发监听的方法)
    tap.delegate = self;
    // 3.为nanaImgView 添加Tap手势识别器对象
    [self.nanaImgView addGestureRecognizer:tap];
}
#define kRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0]
// 监听的方法
- (void)taping
{
    // 每次tap,随机变换背景颜色
    self.view.backgroundColor = kRandomColor;
    NSLog(@"-----taping");
}
#pragma mark - gestureRecognizer的代理方法
//  当点击view的时候,会先询问这个方法,是否接收本次tap点击(即是否为有效tap)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    CGPoint pos = [touch locationInView:touch.view];
    // 点击图片的左半边有效,右半边无效
    if (pos.x <= self.nanaImgView.frame.size.width * 0.5) {
        return YES;
    }
    return NO;
}




#pragma mark - 连线方法
- (IBAction)dismiss
{
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end

Swipe轻扫手势


LongPress长按手势




长按手势的主要属性参数



//
//  SwipeLongPressController.m
//  38_手势
//
//  Created by beyond on 14-9-17.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "SwipeLongPressController.h"

@interface SwipeLongPressController ()
@property (weak, nonatomic) IBOutlet UIImageView *nanaImgView;
- (IBAction)dismiss;

@end

@implementation SwipeLongPressController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 1.允许交互
    _nanaImgView.userInteractionEnabled = YES;
    
    // 2.自定义方法,添加swipe手势
    [self addSwipe];
    
    // 3.自定义方法,添加longPress手势
    [self addLongPress];
}

// 2.自定义方法,添加swipe手势
- (void)addSwipe
{
    // 1.创建Swipe手势识别器对象,同时绑定监听方法(识别到了对应的手势,就会调用监听方法)
    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swiping)];
    // 设置属性:轻扫的方向
    swipe.direction = UISwipeGestureRecognizerDirectionUp;
    // 2.为nanaImgView 添加Swipe手势识别器对象
    [self.nanaImgView addGestureRecognizer:swipe];
}
// 3.自定义方法,添加longPress手势
- (void)addLongPress
{
    // 1.创建LongPress手势识别器对象,同时绑定监听方法(识别到了对应的手势,就会调用监听方法)
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] init];
    [longPress addTarget:self action:@selector(longPressing)];
    
    // 设置属性:至少长按2秒,默认0.5秒
    longPress.minimumPressDuration = 2;
    // 按下之后,不松手,在能触发手势之前,可允许移动的范围,50px范围内长按有效,默认是10px
    longPress.allowableMovement = 50;
    
    // 2.为nanaImgView 添加Swipe手势识别器对象
    [self.nanaImgView addGestureRecognizer:longPress];
}
#define kRandomColor [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1.0]
// 手势的监听的方法
- (void)swiping
{
    self.view.backgroundColor = kRandomColor;
    NSLog(@"-----swiping");
}
// 手势的监听的方法
- (void)longPressing
{
    self.view.backgroundColor = kRandomColor;
    NSLog(@"-------长按了nanaImgView");
}



- (IBAction)dismiss
{
    [self dismissViewControllerAnimated:YES completion:nil   ];
}
@end


Pinch和Rotation手势


捏合(缩放)和旋转


最终效果图:




//
//  PinchRotationController.m
//  38_手势
//
//  Created by beyond on 14-9-17.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "PinchRotationController.h"

// 手势识别器的代理方法,目的是:
@interface PinchRotationController ()<UIGestureRecognizerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *nanaImgView;
- (IBAction)dismiss;

@end

@implementation PinchRotationController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 同时添加Pinch捏合手势(缩放) 和旋转手势
    [self addPinchAndRotate];
}



#pragma mark - 缩放 + 旋转
- (void)addPinchAndRotate
{
    // 1.添加 Pinch捏合手势(缩放)
    [self addPinch];
    // 2.添加 旋转手势
    [self addRotate];
}

// 1.添加 Pinch捏合手势(缩放) ,缩放手势(捏合手势)
- (void)addPinch
{
    // 1.创建Pinch手势识别器对象,同时绑定监听方法(识别到了对应的手势,就会调用监听方法)
    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinching:)];
    // 2.设置代理???
    pinch.delegate = self;
    // 3.为nanaImgView 添加Pinch手势识别器对象
    [self.nanaImgView addGestureRecognizer:pinch];
}

// 2.添加 旋转手势
- (void)addRotate
{
    // 1.创建Rotation手势识别器对象,同时绑定监听方法(识别到了对应的手势,就会调用监听方法)
    UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotating:)];
    // 2.设置代理???
    rotate.delegate = self;
    // 3.为nanaImgView 添加Rotation手势识别器对象
    [self.nanaImgView addGestureRecognizer:rotate];
}
#pragma mark - 重要~~~~手势的监听方法
// Pinch捏合(缩放)
- (void)pinching:(UIPinchGestureRecognizer *)pinch
{
    // X Y 按比例进行缩放
    pinch.view.transform = CGAffineTransformScale(pinch.view.transform, pinch.scale, pinch.scale);
    // 每次重新归零~~~
    pinch.scale = 1; // 这个真的很重要!!!!!
}
// 旋转手势
- (void)rotating:(UIRotationGestureRecognizer *)rotate
{
    // 按手势识别器 的旋转角度进行旋转
    rotate.view.transform = CGAffineTransformRotate(rotate.view.transform, rotate.rotation);
    // 每次要重新归零~~~~
    rotate.rotation = 0; // 这个很重要!!!!!
}

#pragma mark - 手势识别器的代理方法
/**
 *  是否允许多个手势识别器同时有效
 *  Simultaneously : 同时地
 */
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

#pragma mark - 连线方法
- (IBAction)dismiss
{
    [self dismissViewControllerAnimated:YES completion:nil   ];
}
@end





涂鸦

最终效果图:


iOS_38_手势_第17张图片


控制器

//
//  PaintController.m
//  38_手势_涂鸦
//
//  Created by beyond on 14-9-17.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  涂鸦控制器

#import "PaintController.h"
// 画布
#import "Canvas.h"


@interface PaintController ()
// 画板
@property (weak, nonatomic) IBOutlet Canvas *canvasView;

// 清除画板
- (IBAction)clear;
// 撤销
- (IBAction)undo;
// 保存至相册
- (IBAction)save;

@end

@implementation PaintController



// 清除画板
- (IBAction)clear
{
    [self.canvasView clear];
}
// 撤销
- (IBAction)undo
{
    [self.canvasView undo];
}
// 保存至相册
- (IBAction)save
{
    // 1.截图
    UIImage *image = [UIImage captureWithView:self.canvasView];
    
    // 2.保存到图片,建议使用系统推荐的回调方法
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}

// 保存图片操作之后就会调用本方法
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    if (error) { // 保存失败
        [MBProgressHUD showError:@"保存失败"];
    } else { // 保存成功
        [MBProgressHUD showSuccess:@"保存成功"];
    }
}

@end


自定义View:画布

//
//  Canvas.h
//  38_手势_涂鸦
//
//  Created by beyond on 14-9-17.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  画布

#import <UIKit/UIKit.h>

@interface Canvas : UIView
// 清除画板
- (void)clear;
// 撤销上一笔画
- (void)undo;
@end


//
//  Canvas.m
//  38_手势_涂鸦
//
//  Created by beyond on 14-9-17.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  画布,核心代码

#import "Canvas.h"

@interface Canvas()
// 存放贝塞尔路径对象数组,每一次touchBegin,对应一个新的路径
@property (nonatomic, strong) NSMutableArray *pathArr;
@end

@implementation Canvas
#pragma mark - 懒加载
- (NSMutableArray *)pathArr
{
    if (_pathArr == nil) {
        _pathArr = [NSMutableArray array];
    }
    return _pathArr;
}
// 清除画板
- (void)clear
{
    [self.pathArr removeAllObjects];
    [self setNeedsDisplay];
}
// 撤销上一笔画
- (void)undo
{
    [self.pathArr removeLastObject];
    [self setNeedsDisplay];
}
#pragma mark - Touch方法
// 每一次touchBegin,对应一个新的路径对象
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 1.获得当前的触摸点
    UITouch *touch = [touches anyObject];
    CGPoint startPos = [touch locationInView:touch.view];
    
    // 2.创建一个新的路径
    UIBezierPath *currenPath = [UIBezierPath bezierPath];
    currenPath.lineCapStyle = kCGLineCapRound;
    currenPath.lineJoinStyle = kCGLineJoinRound;
    
    // 设置起点
    [currenPath moveToPoint:startPos];
    
    // 3.添加路径到数组中
    [self.pathArr addObject:currenPath];
    
    [self setNeedsDisplay];
}

// 取出最新的贝塞尔路径,添加新的点进去
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint pos = [touch locationInView:touch.view];
    
    UIBezierPath *currentPath = [self.pathArr lastObject];
    [currentPath addLineToPoint:pos];
    
    [self setNeedsDisplay];
}

// 抬笔时,与move一样
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesMoved:touches withEvent:event];
}
#pragma mark - 画线
- (void)drawRect:(CGRect)rect
{
    [[UIColor redColor] set];
    
    for (UIBezierPath *path in self.pathArr) {
        path.lineWidth = 10;
        [path stroke];
    }
}
#pragma mark - 测试C画线代码
- (void)testPath
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //    CGContextMoveToPoint(ctx, 0, 0);
    //    CGContextAddLineToPoint(ctx, 100, 100);
    //    CGContextStrokePath(ctx);
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 0, 0);
    CGPathAddLineToPoint(path, NULL, 100, 100);
    CGContextAddPath(ctx, path);
    
    CGMutablePathRef path2 = CGPathCreateMutable();
    CGPathMoveToPoint(path2, NULL, 250, 250);
    CGPathAddLineToPoint(path2, NULL, 110, 100);
    CGContextAddPath(ctx, path2);
    
    
    CGContextStrokePath(ctx);
    
    CGPathRelease(path);
}
@end


截图分类

//
//  UIImage+ScreenShot.m
//  38_手势
//
//  Created by beyond on 14-9-17.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  分类,截图

#import "UIImage+ScreenShot.h"

@implementation UIImage (ScreenShot)

+ (instancetype)captureWithView:(UIView *)view
{
    // 1.开启上下文
    UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
    
    // 2.将控制器view的layer渲染到上下文
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    
    // 3.取出图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    // 4.结束上下文
    UIGraphicsEndImageContext();
    
    return newImage;
}
@end








































你可能感兴趣的:(ios,手势识别)