IOS笔记051-手势使用
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-手势使用的更多相关文章
- 在iOS上增加手势锁屏、解锁功能
在iOS上增加手势锁屏.解锁功能 在一些涉及个人隐私的场景下,尤其是当移动设备包含太多私密信息时,为用户的安全考虑是有必要的. 桌面版的QQ在很多年前就考虑到用户离开电脑后隐私泄露的危险,提供了“离开 ...
- 荼菜的iOS笔记--UIView的几个Block动画
前言:我的第一篇文章荼菜的iOS笔记–Core Animation 核心动画算是比较详细讲了核心动画的用法,但是如你上篇看到的,有时我们只是想实现一些很小的动画,这时再用coreAnimation就会 ...
- iOS阶段学习第35天笔记(Touch手势介绍)
一.Touch手势 1.利用手势实现UIButton移动效果 实例代码 1) 创建一个继承自UIButton的类 MyButton.h 代码实现 #import <UIKit/UIKit.h ...
- IOS 学习笔记 2015-04-15 手势密码(原)
// // WPSignPasswordView.h // 网投网 // // Created by wangtouwang on 15/4/9. // Copyright (c) 2015年 wan ...
- 轻松实现Android,iOS的一个手势动画效果
先来看效果 这是iOS下的效果,android下完全一致.通过do_GestureView组件和do_Animation组件,deviceone能很容易实现复杂的跨平台纯原生动画效果,这个示例就是通过 ...
- iOS开发摇动手势实现详解
1.当设备摇动时,系统会算出加速计的值,并告知是否发生了摇动手势.系统只会运动开始和结束时通知你,并不会在运动发生的整个过程中始终向你报告每一次运动.例如,你快速摇动设备三次,那只会收到一个摇动事件. ...
- 【IOS笔记】Gesture Recognizers
Gesture Recognizers Gesture recognizers convert low-level event handling code into higher-level acti ...
- 【IOS笔记】About Events in iOS
About Events in iOS Users manipulate their iOS devices in a number of ways, such as touching the scr ...
- 【IOS笔记】Using View Controllers in Your App
参考:http://www.cnblogs.com/patientAndPersist/p/3279645.html Using View Controllers in Your App Whethe ...
- 【IOS笔记】Views
Views Because view objects are the main way your application interacts with the user, they have many ...
随机推荐
- 高德地图 获取sha1
开发版本sha1 控制台输入 cd .android 回车 再输入 keytool -list -v -keystore debug.keystore 回车 输入密钥库口令: andorid ...
- iOS核心动画高级技巧之图层变换和专用图层(二)
iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...
- LeetCode Add Two Numbers 两个数相加
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...
- 详细讲解:使用tp3.2.3完成简单的注册登录功能
使用3.2.3进行了一个简单不过的注册登录功能,界面介绍: 1.注册: 2.登录: 3.登录成功后: 没错,就是简单的让你特别容易上手,上面运用到的知识有: (1)自动验证.自动完成 (2)sessi ...
- 用rem实现h5页面的编写
一 静态页面的布局 将这段代码加到script中 (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orienta ...
- Python风格规范-FYI
Python风格规范 分号 Tip 不要在行尾加分号, 也不要用分号将两条命令放在同一行. 行长度 Tip 每行不超过80个字符 例外: 长的导入模块语句 注释里的URL 不要使用反斜杠连接行. Py ...
- 【BZOJ3460】Jc的宿舍(树上莫队+树状数组)
点此看题面 大致题意: 一棵树,每个节点有一个人,他打水需要\(T_i\)的时间,每次询问两点之间所有人去打水的最小等待时间. 伪·强制在线 这题看似强制在线,但实际上,\(pre\ mod\ 2\) ...
- [论文理解]MetaAnchor: Learning to Detect Objects with Customized Anchors
MetaAnchor: Learning to Detect Objects with Customized Anchors Intro 本文我其实看了几遍也没看懂,看了meta以为是一个很高大上的东 ...
- 小波变换(wavelet transform)的通俗解释(一)
小波变换 小波,一个神奇的波,可长可短可胖可瘦(伸缩平移),当去学习小波的时候,第一个首先要做的就是回顾傅立叶变换(又回来了,唉),因为他们都是频率变换的方法,而傅立叶变换是最入门的,也是最先了解的, ...
- Linux监控二之cacti简单安装部署
目录 cacti简单部署 1 环境依赖包部署 1 1. cacti中文版0.8e搭建 2 2. cacti安装向导 url:http://192.168.200.243/ ...