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 ...
随机推荐
- 阿里 EasyExcel 7 行代码优雅地实现 Excel 文件生成&下载功能
欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...
- 2018.5.22 Oracle安装配置在虚拟机中外部电脑连接服务
1.拷贝老师的集成文件(win系统和oracle服务) 2.安装虚拟机,并且打开镜像文件 3.启动监听程序(实例服务[自动].监听服务) 4.查看虚拟机ip,此ip要主机ip在同一个网段 5.检查虚拟 ...
- python_43_移动文件指针补充
#移动文件指针补充 ''' 文件对象.seek((offset,where)) offset:移动的偏移量,单位为字节.等于正数时向文件尾方向移动,等于负数时向文件头方向移动文件指针 where:指针 ...
- python_20_列表
#1 names=["QiZhiguang","DaiYang","HuZhongtao","ZhangDong"] p ...
- SQL 值得记住的点
概要 记录在学习过程中,遇到的不懂且需要掌握的知识点.主要基于 MySQL. 汇总 replace 函数 删除重复 取子串 substr 项连接 ...
- 黑马基础阶段测试题:定义一个int类型的数组,数组中元素为{5,7,3,9,4}。求出数组中的最小值,并判断最小值是否为偶数,如果是偶数则输出“最小值为偶数”,如果不是偶数则输出“最小值为奇数”。打印如下:
package com.swift; import java.util.Arrays; public class ArrayTest { public static void main(String[ ...
- AT2386 Colorful Hats (乱搞题,思维题)
分情况讨论的神题... max不等于min + 1 或者不等于min,这种情况显然不存在. 如果都等于一个数 有两种情况: 互相独立,那么a[i]肯定==n-1 有相同的,那么a[i]一定不是独立的. ...
- IDEA整合Mybatis+Struts2+Spring(一)--新建项目
1.IDEA新建Maven项目: (1)依次点击File->New->Project,弹出如下对话框: (2)在弹出的New Project页面上,①选择Maven,② 勾选Create ...
- PHP 二维数组某个字段进行排序
/** * @param $arrUsers * @return mixed *二维数组某个字段进行排序 */ function quick_sort($arrUsers) { $sort = arr ...
- JZOJ 5347. 遥远的金字塔
Description Input Output Sample Input 5 3 1 6 1 5 3 5 4 4 4 4 Sample Output 15 Data Constraint 做法: 其 ...