文档章节

IOS初级教程2:UITapGestureRecognizer手势识别的简单使用

一叶博客
 一叶博客
发布于 2014/05/07 17:19
字数 1985
阅读 1201
收藏 1
点赞 0
评论 0

一、从零开始创建项目

    1.为了大家方便理解,我们从一个空项目开始创建2.项目的配置情况如下,可以根据自己随意调整3. 因为我们创建的是新项目,除了一个ILAppDelegate什么都没有


4.正常情况下我们会创建一个根RootViewController,然后通过Controller控制视图的显示逻辑,这里只是一个练习,我们尝试一下新的作法,不要MVC模型了

没有Controller.....

5.我们在屏幕上看到的就是IOS的视图,所有的可显示组件都是UIView的子类(底层的先不考虑)包括UIWindow,其中UIWindow的一个方法

- (void)makeKeyAndVisible;



官方给的解释如下:
convenience. most apps call this to show the main window and also make it key.
所以我们要做的就是创建一系列的视图并把这些视图加入到一个UIWindow中,最后将UIWindow显示到屏幕上

思路有了,下一步就是具体的实现

在ILTapWindow.m中实现如下代码

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self doInit];
    }
    return self;
}

- (void)doInit
{
    //创建一个测试的View,我们将手势添加到这个绿色的View上
    UIView *greenView = [[UIView alloc] initWithFrame:self.bounds];
    greenView.backgroundColor = [UIColor greenColor];
    //将greenView添加到当前window上
    [self addSubview:greenView];
    
    //创建一个Tap手势
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    //将手势添加到greenView上,这样才将手势与view关联起来
    [greenView addGestureRecognizer:gesture];
}

- (void)handleTap:(UITapGestureRecognizer *)gesture
{
    //我们获取gesture关联的view,并将view的类名打印出来
    NSString *className = NSStringFromClass([gesture.view class]);
    NSLog(@"您点击了%@", className);
}



这样我们就将视图及手势相关逻辑处理好了,下一步我们要将ILTapWindow显示在屏幕上,回到ILAppDelegate.m的入口方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[ILTapWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window makeKeyAndVisible];
    return YES;
}



6.所有逻辑基本都写好了,我们点击运行一下吧(项目下载地址: http://git.oschina.net/green/ILTapGestureRecognizer/repository/archive?ref=第一部分)


二、通过附加透明View实现区域性识别方法

1.看起来好像没有什么难度,大体思路不就是把UITapGestureRecognizer加到UIView中。事实确实是这样的,可问题又来了,如果我想将手势添加到绿色视图的下半部分

2.思考了一会儿,好像确实不那么好处理

但是这点可难不到我广大程序员,于是Baidu Google,后给出一个答案,添加一个透明的UIView,将UITapGestureRecognizer添加到这个透明的UIView不就可以了


面包和馒头都会有的

3.动手实现

@implementation ILTapWindow

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self doInit];
    }
    return self;
}

- (void)doInit
{
    //创建一个测试的View,我们将手势添加到这个绿色的View上
    UIView *greenView = [[UIView alloc] initWithFrame:self.bounds];
    greenView.backgroundColor = [UIColor greenColor];
    //将greenView添加到当前window上
    [self addSubview:greenView];
    CGRect bounds= greenView.bounds;
    CGRect tapArea = CGRectMake(0, CGRectGetHeight(bounds) / 2, CGRectGetWidth(bounds), CGRectGetHeight(bounds));
    [self addGestureArea:tapArea forView:greenView];
   
}

- (void)addGestureArea:(CGRect)frame forView:(UIView *)view
{
    UIView *gestureView = [[UIView alloc] initWithFrame:frame];
    //此处将设置为[UIColor clearColor]UIView会变为透明,这里为了测试方便把color设为红色
    gestureView.backgroundColor = [UIColor redColor];
    //创建一个Tap手势
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    //将手势添加到greenView上,这样才将手势与view关联起来
    [gestureView addGestureRecognizer:gesture];
    
    [view addSubview:gestureView];
    
}

- (void)handleTap:(UITapGestureRecognizer *)gesture
{
    //我们获取gesture关联的view,并将view的类名打印出来
    NSString *className = NSStringFromClass([gesture.view class]);
    NSLog(@"您点击了%@", className);
}

@end



执行一下(项目下载地址 http://git.oschina.net/green/ILTapGestureRecognizer/repository/archive?ref=第二部分)

4.需求总是再变的,一天设计师要求点击屏幕,在上方推出工具条,再次点击屏幕隐藏工具条,快速实现一下:

#import "ILTapWindow.h"
#define TOOLS_VIEW_HEIGHT (44 + 10)

@interface ILTapWindow ()
//用于保存工具条的指针
@property (weak, nonatomic) UIView *toolsBar;
@end

@implementation ILTapWindow

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self doInit];
    }
    return self;
}

- (void)doInit
{
    [self configBackgroundView];
    [self configToolsBar];
    
}

- (void)configBackgroundView
{
    //创建一个测试的View,我们将手势添加到这个绿色的View上
    UIView *greenView = [[UIView alloc] initWithFrame:self.bounds];
    greenView.backgroundColor = [UIColor greenColor];
    //将greenView添加到当前window上
    [self addSubview:greenView];
    [self addGestureArea:greenView.bounds forView:greenView];
}

- (void)configToolsBar
{
    CGRect frame = CGRectMake(0, -TOOLS_VIEW_HEIGHT, CGRectGetWidth(self.frame), TOOLS_VIEW_HEIGHT);
    UIView *tools = [[UIView alloc] initWithFrame:frame];
    tools.backgroundColor = [UIColor yellowColor];
    [self addSubview:tools];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    button.backgroundColor = [UIColor blueColor];
    button.frame = CGRectMake(10, 10, 40, 40);
    [button setTitle:@"打印" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [tools addSubview:button];
    self.toolsBar = tools;
}

- (void)buttonPressed:(UIButton *)button
{
    NSLog(@"=============点击了Button==============");
    
}

- (void)showToolsBar:(BOOL)show
{
    CGRect frame = self.toolsBar.frame;
    frame.origin.y = show ? 0 : -TOOLS_VIEW_HEIGHT;
    [UIView animateWithDuration:0.3 animations:^{
        self.toolsBar.frame = frame;
    }];
}


- (void)addGestureArea:(CGRect)frame forView:(UIView *)view
{
    UIView *gestureView = [[UIView alloc] initWithFrame:frame];
    gestureView.backgroundColor = [UIColor clearColor];
    //创建一个Tap手势
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    //将手势添加到greenView上,这样才将手势与view关联起来
    gesture.cancelsTouchesInView = NO;
    gesture.delaysTouchesBegan = YES;
    [gestureView addGestureRecognizer:gesture];
    
    [view addSubview:gestureView];
    
}

- (BOOL)isToolsBarShow
{
    //在ios中CGFloat做了优化,是可以直接用==来进行比较,C++不可以
    return self.toolsBar.frame.origin.y == 0;
}

- (void)handleTap:(UITapGestureRecognizer *)gesture
{
    NSLog(@"================点击了屏幕,显隐工具条=========================");
    if (self.isToolsBarShow) {
        [self showToolsBar:NO];
    } else {
        [self showToolsBar:YES];
    }
    
}

@end

结果正如我们希望的那样,点击屏幕显示工具条,再次点击屏幕隐藏工具条。当工具条显示时,我们点击工具条,没有触发手势的点击事件。可是事与愿为,真实的情况并不是这样的,这次我们为了简便直接使用了UIWindow的方法显示UIView,通常情况下,我们的视图的控制是交给UIViewController来处理的,在使用UIViewController的时候,如果工具条是在显示状态时,我们点击工具条也会触发手势点击事件,这个留给大家去测试了,代码只需要稍微修改就能测试出来。(工具条部分下载地址:http://git.oschina.net/green/ILTapGestureRecognizer/repository/archive?ref=第二部分-工具条

三、通过委托实现区域性识别

1.我们知道通过附加透明UIView的方法并不是总起作用,虽然在本次示例中没有问题,但是通过UIViewController管理视图时,就会出现视图穿透的效果,即在底层UIView加了手势,点击上面的UIView也会触发点击手势事件,这并不是我们想要的结果。在另一方面,附加透明UIView的做法在一些情况下,如不想中间区域响应手势点击。这样的话,就得加多个透明的UIView才能实现,有没有更好的方法吗?

我们新建一个类,继承如下:

ILTapGestureRecognizer代码如下:

@interface ILTapGestureRecognizer : UITapGestureRecognizer

@property (unsafe_unretained, nonatomic)CGRect responseFrame;

@end
///////////////////////////////////////////////////////////////////
@interface ILTapGestureRecognizer () <UIGestureRecognizerDelegate>

@end

@implementation ILTapGestureRecognizer

- (id)initWithTarget:(id)target action:(SEL)action
{
    self = [super initWithTarget:target action:action];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    //获取点击坐标
    CGPoint pointPosition = [touch locationInView:gestureRecognizer.view];
    if (CGRectContainsPoint(self.responseFrame, pointPosition)) {
        return YES;
    }
    return NO;
}


@end



当然ILWindow.m文件也需要修改一下

@interface ILTapWindow ()
@end

@implementation ILTapWindow

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self doInit];
    }
    return self;
}

- (void)doInit
{
    //创建一个测试的View,我们将手势添加到这个绿色的View上
    UIView *greenView = [[UIView alloc] initWithFrame:self.bounds];
    greenView.backgroundColor = [UIColor greenColor];
    //将greenView添加到当前window上
    [self addSubview:greenView];
    
    ILTapGestureRecognizer *gesture = [[ILTapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    CGRect bounds= greenView.bounds;
    CGRect tapArea = CGRectMake(0, CGRectGetHeight(bounds) / 2, CGRectGetWidth(bounds), CGRectGetHeight(bounds));
    gesture.responseFrame = tapArea;
    
    [greenView addGestureRecognizer:gesture];
}

- (void)handleTap:(UITapGestureRecognizer *)gesture
{
    //我们获取gesture关联的view,并将view的类名打印出来
    NSString *className = NSStringFromClass([gesture.view class]);
    NSLog(@"您点击了%@", className);
}


@end



2.实现原理

通过UIGestureRecognizerDelegate的接口

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



来决定是否响应手势的点击事件,官方解释如下:

called before touchesBegan:withEvent: is called on the gesture recognizer for a new touch. return NO to prevent the gesture recognizer from seeing this touch

至此点击手势我们就全部学习完了,在项目开发中,我们经常会遇到“三、通过委托实现区域性识别”,这里给的示例比较简单,项目中可能很复杂,我们可以通过定制ILTapGestureRecognizer来实现更加复杂的功能(区域识别下载地址:http://git.oschina.net/green/ILTapGestureRecognizer/repository/archive?ref=第三部-分区域识别

© 著作权归作者所有

共有 人打赏支持
一叶博客
粉丝 16
博文 13
码字总数 16627
作品 0
朝阳
项目经理
如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊 ⋅ 05/26 ⋅ 0

全屏手势返回插件 - BBGestureBack

BBGestureBack Full screen return gesture(全屏手势返回 滑动返回 pop 动画效果) iOS 侧滑返回 BBGestureBack iOS 全屏手势返回 滑动返回 pop 动画效果 现在市场上的主流app都有用到各种侧...

Bonway ⋅ 05/30 ⋅ 0

一样的iOS开发程序员为什么有人4k有人40k?

前言 移动开发真正火起来其实就是最近这几年,iOS 开发技术因为发展也就才这么几年,所以值得做的事情还有很多,这就造成了每年苹果的 WWDC 都会推出一堆新的特性和 API。整体上来说,这对业...

原来是泽镜啊 ⋅ 05/16 ⋅ 0

天生不凡ios怎么在电脑上玩 天生不凡ios电脑版玩法教程

天生不凡ios怎么在电脑上玩呢?现在有很多小伙伴都在玩天生不凡手游,不过相对于传统的在手机上进行游戏,很多人都倾向于新玩法,就是在电脑上玩天生不凡手游。下面小编就给亲们介绍下天生不...

kaopu8520 ⋅ 05/29 ⋅ 0

iOS三维菜单、调试工具、封装通讯录、网络框架、多种控件和动画等源码

iOS精选源码 一个调用系统通讯录和获取通讯录所有联系人的封装(http://www.code4app.com/thread-29726-1-1.html) ios scrollview嵌套tableview同向滑动(初级、进阶), 支持OC / Swift(http...

sunnyaigd ⋅ 05/15 ⋅ 0

iOS自定义弹出视图、收音机APP、图片涂鸦、加载刷新、文件缓存等源码

iOS精选源码 一款优秀的 聆听夜空FM 源码(http://www.code4app.com/thread-14546-1-1.html) zhPopupController 简单快捷弹出自定义视图(http://www.code4app.com/thread-14861-1-1.html) WHS......

sunnyaigd ⋅ 06/04 ⋅ 0

iOS高仿QQ侧滑控件、下载框架、动画效果、扫一扫、颜色变化、K线图等源码

iOS精选源码 仿京东"加入购物车"转场动画(http://www.code4app.com/thread-28162-1-1.html) ColorTool(颜色转换)(http://www.code4app.com/thread-29256-1-1.html) Swift 专业版K线(http://w......

sunnyaigd ⋅ 04/17 ⋅ 0

Appium 1.8.0 发布,全面支持 W3C WebDriver 规范

Appium 是一个开源、跨平台的自动化测试工具,最初主要用于测试原生和轻量移动应用,包括 iOS 和 Android ,目前还支持对 Windows 平台上的应用的自动化测试。 Appium 1.8.0 发布,引入了对 ...

王练 ⋅ 04/25 ⋅ 0

怀旧,开源项目将 Windows 95 画风带到 iOS 上

开发者天马行空的想法总是能够给人带来惊喜,日前有开发者写了一个适用于 iOS 的 Windows 95 经典风格 UI 组件集 ClassicKit,并将其开源在 GitHub 上。 该项目将 Windows 95 的风格带入了 ...

雨田桑 ⋅ 05/17 ⋅ 8

【AR】开始使用Vuforia开发iOS(2)

原 设置iOS开发环境 安装Vuforia iOS SDK 如何安装Vuforia iOS示例 编译并运行Vuforia iOS示例 支持iOS金属 iOS 64位迁移 设置iOS开发环境 适用于iOS的Vuforia引擎目前支持运行iOS 9及更高版...

lichong951 ⋅ 06/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

BS与CS的联系与区别【简】

C/S是Client/Server的缩写。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统,如Oracle、Sybase、InFORMix或 SQL Server。客户端需要安装专用的客户端软件。 B/S是Brower/...

anlve ⋅ 40分钟前 ⋅ 0

发生了什么?Linus 又发怒了?

在一个 Linux 内核 4.18-rc1 的 Pull Request 中,开发者 Andy Shevchenko 表示其在对设备属性框架进行更新时,移除了 union 别名,这引发了 Linus 的暴怒。 这一次 Linus Torvalds 发怒的原...

问题终结者 ⋅ 今天 ⋅ 0

在树莓派上搭建一个maven仓库

在树莓派上搭建一个maven仓库 20180618 lambo init 项目说明 家里有台树莓派性能太慢。想搭建一个maven私服, 使用nexus或者 jfrog-artifactory 运行的够呛。怎么办呢,手写一个吧.所在这个...

林小宝 ⋅ 今天 ⋅ 0

Spring发展历程总结

转自与 https://www.cnblogs.com/RunForLove/p/4641672.html 目前很多公司的架构,从Struts2迁移到了SpringMVC。你有想过为什么不使用Servlet+JSP来构建Java web项目,而是采用SpringMVC呢?...

onedotdot ⋅ 今天 ⋅ 0

Python模块/包/库安装(6种方法)

Python模块/包/库安装(6种方法) 冰颖机器人 2016-11-29 21:33:26 一、方法1: 单文件模块 直接把文件拷贝到 $python_dir/Lib 二、方法2: 多文件模块,带setup.py 下载模块包(压缩文件zip...

cswangyx ⋅ 今天 ⋅ 0

零基础学习大数据人工智能,学习路线篇!系统规划大数据之路?

大数据处理技术怎么学习呢?首先我们要学习Python语言和Linux操作系统,这两个是学习大数据的基础,学习的顺序不分前后。 Python:Python 的排名从去年开始就借助人工智能持续上升,现在它已经...

董黎明 ⋅ 今天 ⋅ 0

openJdk和sun jdk的区别

使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SUN JDK有什么关系和区别呢? 历史上的原因是,Ope...

jason_kiss ⋅ 今天 ⋅ 0

梳理

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 它是JS的状态容器,是一种解决问题的方式,所以即可以用于 react 也可以用于 vue。 需要理解其思想及实现方式。 应用中所有的 stat...

分秒 ⋅ 今天 ⋅ 0

Java 后台判断是否为ajax请求

/** * 是否是Ajax请求 * @param request * @return */public static boolean isAjax(ServletRequest request){return "XMLHttpRequest".equalsIgnoreCase(((HttpServletReques......

JavaSon712 ⋅ 今天 ⋅ 0

Redis 单线程 为何却需要事务处理并发问题

Redis是单线程处理,也就是命令会顺序执行。那么为什么会存在并发问题呢? 个人理解是,虽然redis是单线程,但是可以同时有多个客户端访问,每个客户端会有 一个线程。客户端访问之间存在竞争...

码代码的小司机 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部