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. git push 使用教程

    git push命令用于将本地分支的更新,推送到远程主机.它的格式与git pull命令相仿. $ git push <远程主机名> <本地分支名>:<远程分支名> ...

  2. 初识Notification

    通知(Notification)是 Android 系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现.发出一条通知后,手机最上方 ...

  3. 《Unity預計算即時GI》笔记:二、光照图

    说明 这篇文章是对<Unity預計算即時GI>这个系列文章的笔记. 光照图 什么是光照图 光照图在第三章中有如下的定义,读起来很是费解. 一個光照圖(Chart)是表示一個光照貼圖的區域, ...

  4. mybatis-动态sql1

    在多条件查询的情况下必须用到动态sql 沿用之前的项目 1.在dao中添加多添件查询方法 package com.java1234.mappers; import java.util.List;imp ...

  5. LeetCode Valid Parentheses 有效括号

    class Solution { public: void push(char c){ //插入结点 struct node *n=new struct node; n->nex=; n-> ...

  6. [Asp.Net] MVC 和Web API Action 获取参数的区别

    Asp.net MVC 和web api 的action 在获取从前台传入的数据是有很大不同 前台使用ajax的方式向后台发起post的请求 Content-Type:application/json ...

  7. IOS 进程描述

    ● 什么是进程 ● 进程是指在系统中正在运行的一个应用程序 ● 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 ● 通过“活动监视器”可以查看Mac系统中所开启的进程

  8. Java统计用户年/月/周/日网站访问量

    一:准备工作,引入相关依赖: 二:运行效果图: 下一次访问 三:具体代码如下  (1):CountObjectInfo.java package cn.csrc.base.count; import ...

  9. CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第二节

    原文链接 第二节:第一个内核 Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并 ...

  10. arcgis engine计算点到线的最短距离

    IProximityOperator接口用于获取两个几何图形的距离,以及给定一个Point,求另一个几何图形上离离给定点最近的点.IProximityOperator接口的主要方法有:QueryNea ...