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. 阿里 EasyExcel 7 行代码优雅地实现 Excel 文件生成&下载功能

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  2. 2018.5.22 Oracle安装配置在虚拟机中外部电脑连接服务

    1.拷贝老师的集成文件(win系统和oracle服务) 2.安装虚拟机,并且打开镜像文件 3.启动监听程序(实例服务[自动].监听服务) 4.查看虚拟机ip,此ip要主机ip在同一个网段 5.检查虚拟 ...

  3. python_43_移动文件指针补充

    #移动文件指针补充 ''' 文件对象.seek((offset,where)) offset:移动的偏移量,单位为字节.等于正数时向文件尾方向移动,等于负数时向文件头方向移动文件指针 where:指针 ...

  4. python_20_列表

    #1 names=["QiZhiguang","DaiYang","HuZhongtao","ZhangDong"] p ...

  5. SQL 值得记住的点

    概要 记录在学习过程中,遇到的不懂且需要掌握的知识点.主要基于 MySQL.   汇总      replace 函数      删除重复      取子串 substr      项连接      ...

  6. 黑马基础阶段测试题:定义一个int类型的数组,数组中元素为{5,7,3,9,4}。求出数组中的最小值,并判断最小值是否为偶数,如果是偶数则输出“最小值为偶数”,如果不是偶数则输出“最小值为奇数”。打印如下:

    package com.swift; import java.util.Arrays; public class ArrayTest { public static void main(String[ ...

  7. AT2386 Colorful Hats (乱搞题,思维题)

    分情况讨论的神题... max不等于min + 1 或者不等于min,这种情况显然不存在. 如果都等于一个数 有两种情况: 互相独立,那么a[i]肯定==n-1 有相同的,那么a[i]一定不是独立的. ...

  8. IDEA整合Mybatis+Struts2+Spring(一)--新建项目

    1.IDEA新建Maven项目: (1)依次点击File->New->Project,弹出如下对话框: (2)在弹出的New Project页面上,①选择Maven,② 勾选Create ...

  9. PHP 二维数组某个字段进行排序

    /** * @param $arrUsers * @return mixed *二维数组某个字段进行排序 */ function quick_sort($arrUsers) { $sort = arr ...

  10. JZOJ 5347. 遥远的金字塔

    Description Input Output Sample Input 5 3 1 6 1 5 3 5 4 4 4 4 Sample Output 15 Data Constraint 做法: 其 ...