UIGestureRecognizer

利用UIGestureRecognizer,能轻松识别用户在某个view上面做的一些常见手势
UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势

UITapGestureRecognizer(敲击)

UIPinchGestureRecognizer(捏合,用于缩放)

UIPanGestureRecognizer(拖拽)

UISwipeGestureRecognizer(轻扫)

UIRotationGestureRecognizer(旋转)

UILongPressGestureRecognizer(长按)

使用方法

// 创建点按手势

UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];

// 给imageView添加手势,默认imageView不响应事件

// 设置imageView 响应事件

self.imageView.userInteractionEnabled = YES;

[self.imageView addGestureRecognizer:gesture];

响应手势事件,可以在里面进行形变

// 响应手势事件

- (void)tap:(UITapGestureRecognizer *)tap

{

NSLog(@"%s",__func__);

// 旋转

self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI_4);

}

手势的状态

typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {

// 没有触摸事件发生,所有手势识别的默认状态

UIGestureRecognizerStatePossible,

// 一个手势已经开始但尚未改变或者完成时

UIGestureRecognizerStateBegan,

// 手势状态改变

UIGestureRecognizerStateChanged,

// 手势完成

UIGestureRecognizerStateEnded,

// 手势取消,恢复至Possible状态

UIGestureRecognizerStateCancelled,

// 手势失败,恢复至Possible状态

UIGestureRecognizerStateFailed,

// 识别到手势识别

UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded

};

手势的一些代理方法

#pragma mark -  手势代理方法

// 是否开始手势

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

{

return YES;

}

//是否允许同时支持多个手势,默认是不支持多个手势

// 返回yes表示支持多个手势

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

{

return YES;

}

// 是否允许接收手指的触摸点

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch

{

//    NSLog(@"%@",touch);

return YES;

}

逐个实现每个手势

1、点按 UITapGestureRecognizer

#pragma mark - 各种手势

// UITapGestureRecognizer

// 点按

- (void)tapImage

{

// 创建点按手势

UITapGestureRecognizer *gestur = [[UITapGestureRecognizeralloc] initWithTarget:selfaction:@selector(tap:)];

// 给imageView添加手势,默认imageView不响应事件

gestur.delegate = self;

gestur.numberOfTapsRequired = 2; // 点击次数

[self.imageView addGestureRecognizer:gestur];

}

// 响应点按手势事件

- (void)tap:(UITapGestureRecognizer *)tap

{

// 连续点按两次就更换显示图片

if (tap.numberOfTapsRequired == 2) {

self.imageView.image = [UIImage imageNamed:@"qianbao"];

}

}

2、捏合 可以使用两个手指进行缩放 UIPinchGestureRecognizer

//UIPinchGestureRecognizer

// 捏合,可以缩放

- (void)pinchImage

{

UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizeralloc] initWithTarget:selfaction:@selector(pinch:)];

//pinch.delegate = self;

[self.imageViewaddGestureRecognizer:pinch];

}

- (void)pinch:(UIPinchGestureRecognizer *)pinch

{

self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale,pinch.scale);

// 复位

pinch.scale = 1;

}

3、长按 UILongPressGestureRecognizer

// UILongPressGestureRecognizer

// 长按,默认会触发两次,开始时调用一次,结束时调用一次,可以根据手势状态

- (void)longPressImage

{

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizeralloc] initWithTarget:selfaction:@selector(longPress:)];

[self.imageView addGestureRecognizer:longPress];

}

- (void)longPress:(UILongPressGestureRecognizer *)longP

{

// 判断手势状态,只在手势开始的时候执行。

if(longP.state == UIGestureRecognizerStateBegan)

{

self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI);

}

}

4、清扫 轻轻向某个方向滑动

// UISwipeGestureRecognizer

// 清扫手势,默认向右

- (void)swipeImage

{

UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizeralloc] initWithTarget:selfaction:@selector(swipe:)];

[self.imageViewaddGestureRecognizer:swipe];

// 如果以后想要一个控件支持多个方向的轻扫,必须创建多个轻扫手势,一个轻扫手势只支持一个方向

// 默认轻扫的方向是往右

UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizeralloc] initWithTarget:selfaction:@selector(swipe:)];

swipeUp.direction = UISwipeGestureRecognizerDirectionUp;

[self.imageView addGestureRecognizer:swipeUp];

}

- (void)swipe:(UISwipeGestureRecognizer *)swipe

{

// 输出状态

NSLog(@"%s\n%ld",__func__,swipe.direction);

}

5、旋转 UIRotationGestureRecognizer

// UIRotationGestureRecognizer

// 旋转手势

- (void)rotateImage

{

UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotate:)];

[self.imageView addGestureRecognizer:rotate];

}

- (void)rotate:(UIRotationGestureRecognizer *)rotate

{

self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotate.rotation);

// 复位

rotate.rotation = 0;

}

6、拖拽  UIPanGestureRecognizer

// 拖拽

- (void)panImage

{

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizeralloc] initWithTarget:selfaction:@selector(pan:)];

[self.imageViewaddGestureRecognizer:pan];

}

- (void)pan:(UIPanGestureRecognizer *)pan

{

// 获取手势移动点

CGPoint curP = [pan translationInView:self.imageView];

self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, curP.x, curP.y);

// 复位,一定要复位

[pan setTranslation:CGPointZeroinView:self.imageView];

}

在视图加载时进行调用即可

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

// 设置imageView 响应事件

self.imageView.userInteractionEnabled = YES;

// 点按图形

[self tapImage];

// 长按

[selflongPressImage];

// 清扫

[self swipeImage];

// 旋转

[self rotateImage];

// 缩放

[self pinchImage];

// 拖拽

//    [self panImage];

}

简单效果如下

手势使用例子-抽屉效果

抽屉效果的实现

1、需要三个视图,一个主视图,两个底部视图

@property (nonatomic,weak) UIView *mainView;

@property (nonatomic,weak) UIView *leftView;

@property (nonatomic,weak) UIView *rightView;

2、初始化界面

// 初始化界面

- (void)initUI

{

// 左划显示视图

UIView *left = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];

self.leftView = left;

self.leftView.backgroundColor  = [UIColorblueColor];

[self.view addSubview:self.leftView];

// 右划显示视图

UIView *right = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];

self.rightView = right;

self.rightView.backgroundColor  = [UIColorgreenColor];

[self.view addSubview:self.rightView];

// 主视图

UIView *main = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];

self.mainView = main;

self.mainView.backgroundColor  = [UIColorredColor];

[self.view addSubview:self.mainView];

}

3、添加手势

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

// 初始化界面

[self initUI];

//添加手势

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizeralloc] initWithTarget:selfaction:@selector(pan:)];

[self.view addGestureRecognizer:pan];

}

   

   手势监听方法

 

#define kLeft -250

#define kRight 275

- (void)pan:(UIPanGestureRecognizer *)pan

{

//获取当前点

CGPoint curP = [pan translationInView:self.view]; // 转换指定view的位置

// x轴偏移,y轴改变,宽度高度都跟着改变

self.mainView.frame = [self frameWithOffsetX:curP.x];

// 更新几个视图的状态

[self observeValueForKeyPath:nil ofObject:nil change:nil context:nil];

// 复位

[pan setTranslation:CGPointZero inView:self.view];

// 定位,手势结束后进行判断

if (pan.state == UIGestureRecognizerStateEnded) {

// 左划

CGFloat target = 0;

//  如果向右滑动操作屏幕的一半就定位到 275

if (self.mainView.frame.origin.x > kWidth * 0.5) {

target = kRight;

}

// 否则就定位到 -250

else if(CGRectGetMaxX(self.mainView.frame) < kWidth * 0.5)

{

target = kLeft;

}

// 获得x轴的偏移量

CGFloat offsetX = target - self.mainView.frame.origin.x ;

[UIView animateWithDuration:0.25 animations:^{

if (target == 0)

{

self.mainView.frame = self.view.bounds;

}

else

{

self.mainView.frame = [self frameWithOffsetX:offsetX];

}

}];

}

}

每次滑动时都要判断要显示的底部视图,显示left还是right,根据x值就可以判断

// 监听frame属性的改变

// 只要监听的属性一改变,就会调用观察者的这个方法,通知你有新值

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

// 更新几个视图的状态

// 判断x坐标大小,大于0向右滑动,小于0 向左滑动

if(self.mainView.frame.origin.x > 0)

{

self.rightView.hidden = YES;

self.leftView.hidden = NO;

}

else

{

self.rightView.hidden = NO;

self.leftView.hidden = YES;

}

}

每次滑动都要随时判断frame的状态,在方法 frameWithOffsetX 中进行判断 

#define kWidth 80 // 距离顶部最大距离

// 计算frame的位置信息

- (CGRect)frameWithOffsetX:(CGFloat)offsetX

{

CGRect frame = self.mainView.frame;

// 获得x轴偏移量

frame.origin.x += offsetX;

// 获得屏幕宽度好高度

CGFloat screenW = [UIScreenmainScreen].bounds.size.width;

CGFloat screenH = [UIScreenmainScreen].bounds.size.height;

// y轴偏移量

CGFloat offsetY = offsetX * kWidth / screenW;

// 获得上一次的高度

CGFloat preH = frame.size.height;

// 获得上一次的宽度

CGFloat preW = frame.size.width;

// 当前的高度

CGFloat curH = preH - 2 * offsetY;

if (frame.origin.x < 0) {

curH = preH + 2 * offsetY;

}

// 获取缩放比例

CGFloat scale = curH / preH;

// 当前的宽度

CGFloat curW = preW * scale;

// 设置frame

frame.origin.y = (screenH - curH) / 2;

frame.size.height = curH;

frame.size.width = curW;

return frame;

}

4、自动提示宏

在使用KVO对某个属性进行监听时,如果参数直接传入字符串,很有可能写错。可以使用自动提示宏来自动提示要监视的属性。

// 使用KVO时刻监听属性的改变

// Observer:观察者 谁想监听

// KeyPath:监听的属性

// options:监听新值的改变

[self.mainViewaddObserver:selfforKeyPath:keyPath(self.mainView, frame) options:NSKeyValueObservingOptionNewcontext:nil];

// 为了防止给属性添加监视器时写错,可以使用自动提示宏来传参数

[self.mainView addObserver:self forKeyPath:@“frame”options:NSKeyValueObservingOptionNew context:nil];

在方法  observeValueForKeyPath  中对属性改变进行监听。

宏的书写规则

// 自动提示宏

// 宏的操作原理,每输入一个字母就会直接把宏右边的拷贝,并且会自动补齐前面的内容。

// 宏里面的#,会自动把后面的参数变成C语言的字符串,

// (obj.keyPath,keyPath) 逗号表达式,最终结果取keyPath

// void表示不使用这个参数的返回结果

// @() 表示把c语言字符串转换成OC字符串

#define keyPath(obj,keyPath) @(((void)obj.keyPath,#keyPath))

IOS笔记051-手势使用的更多相关文章

  1. 在iOS上增加手势锁屏、解锁功能

    在iOS上增加手势锁屏.解锁功能 在一些涉及个人隐私的场景下,尤其是当移动设备包含太多私密信息时,为用户的安全考虑是有必要的. 桌面版的QQ在很多年前就考虑到用户离开电脑后隐私泄露的危险,提供了“离开 ...

  2. 荼菜的iOS笔记--UIView的几个Block动画

    前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...

  3. iOS阶段学习第35天笔记(Touch手势介绍)

    一.Touch手势 1.利用手势实现UIButton移动效果  实例代码 1) 创建一个继承自UIButton的类 MyButton.h  代码实现 #import <UIKit/UIKit.h ...

  4. IOS 学习笔记 2015-04-15 手势密码(原)

    // // WPSignPasswordView.h // 网投网 // // Created by wangtouwang on 15/4/9. // Copyright (c) 2015年 wan ...

  5. 轻松实现Android,iOS的一个手势动画效果

    先来看效果 这是iOS下的效果,android下完全一致.通过do_GestureView组件和do_Animation组件,deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过 ...

  6. iOS开发摇动手势实现详解

    1.当设备摇动时,系统会算出加速计的值,并告知是否发生了摇动手势.系统只会运动开始和结束时通知你,并不会在运动发生的整个过程中始终向你报告每一次运动.例如,你快速摇动设备三次,那只会收到一个摇动事件. ...

  7. 【IOS笔记】Gesture Recognizers

    Gesture Recognizers Gesture recognizers convert low-level event handling code into higher-level acti ...

  8. 【IOS笔记】About Events in iOS

    About Events in iOS Users manipulate their iOS devices in a number of ways, such as touching the scr ...

  9. 【IOS笔记】Using View Controllers in Your App

    参考:http://www.cnblogs.com/patientAndPersist/p/3279645.html Using View Controllers in Your App Whethe ...

  10. 【IOS笔记】Views

    Views Because view objects are the main way your application interacts with the user, they have many ...

随机推荐

  1. C#添加删除防火墙例外(程序、端口)

    一. 添加 COM 引用 在引用里,选择 COM 页, 找到 NetFwTypeLib , 确定即可 二. 添加允许通过防火墙的例外程序 using System; using System.Coll ...

  2. Notification高级技巧

    观察Notification这个类,你会发现里面还有很多我们没有使用过的属性.先来看看sound这个属性吧,它可以在通知发出的时候播放一段音频,这样就能够更好地告知用户有通知到来.sound 这个属性 ...

  3. 1)实际时间(real time): 从command命令行开始执行到运行终止的消逝时间; 2)用户CPU时间(user CPU time): 命令执行完成花费的用户CPU时间,即命令在用户态中执行时间总和; 3)系统CPU时间(system CPU time): 命令执行完成花费的系统CPU时

    1)实际时间(real time): 从command命令行开始执行到运行终止的消逝时间: 2)用户CPU时间(user CPU time): 命令执行完成花费的用户CPU时间,即命令在用户态中执行时 ...

  4. CentOs7 修复 引导启动

    一.修复MBR: MBR(Master Boot Record主引导记录): 硬盘的0柱面.0磁头.1扇区称为主引导扇区.其中446Byte是bootloader,64Byte为Partition t ...

  5. UVA Live Archive 4490 Help Bubu(状压dp)

    难点在于状态设计,从左向右一本书一本书的考虑,每本书的决策有两种拿走或者留下, 对于拿走后的书,之后要放回,但是决策过程中不知道到往哪里放, 虽然前面的书的种类确定,可能是往后面放更优,而后面的书的类 ...

  6. 2018.2.8 php实现qq登陆接口

    PHP实现QQ登录的原理和实现过程 2018-02-08 学习与分享 PHP自学中心 第三方登录,就是使用大家比较熟悉的比如QQ.微信.微博等第三方软件登录自己的网站,这可以免去注册账号.快速留住用户 ...

  7. 如何更改VirtualBox虚拟电脑内存大小

  8. AngularJS 数组

    AngularJS数组就像Javascript数组 <!DOCTYPE html><html><head><meta http-equiv="Con ...

  9. C#自减运算符

    一.C#自减运算符(--) 自减运算符(--)是将操作数减1. 1. 前缀自减运算符 前缀自减运算符是“先减1,后使用”.它的运算结果是操作数减1之后的值. 例如: --x;  // 前缀自减运算符 ...

  10. 2018年ElasticSearch6.2.2教程ELK搭建日志采集分析系统(教程详情)

    章节一  2018年 ELK课程计划和效果演示1.课程安排和效果演示    简介:课程介绍和主要知识点说明,ES搜索接口演示,部署的ELK项目演示    es: localhost:9200    k ...