在iOS应用开发中,有三类视图对象会打开虚拟键盘,进行输入操作,但如何关闭虚拟键盘,却没有提供自动化的方法。这个需要我们自己去实现。这三类视图对象分别是UITextField,UITextView和UISearchBar。 这里介绍一下UITextField中关闭虚拟键盘的几种方法。

(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1753330 )

第一种方法,使用它的委托UITextFieldDelegate中的方法textFieldShouldReturn:来关闭虚拟键盘。 在UITextField视图对象如birdNameInput所在的类中实现这个方法。

  1. - (BOOL)textFieldShouldReturn:(UITextField *)textField {
  2. if ((textField == self.birdNameInput) || (textField == self.locationInput)) {
  3. [textField resignFirstResponder];
  4. }
  5. return YES;
  6. }
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ((textField == self.birdNameInput) || (textField == self.locationInput)) {
[textField resignFirstResponder];
}
return YES;
}

这样,在输入框birdNameInput中打开虚拟键盘后,轻击键盘的return键就会自动关闭掉虚拟键盘。
第二种方法,将birdNameInput的属性中Return Key修改为done,再定义一个方法和Done键的Did End On Exit连接。通过轻击done键触发这个事件来关闭虚拟键盘。 定义的方法如下:

  1. - (IBAction) textFieldDoneEditing:(id)sender
  2. {
  3. [sender resignFirstResponder];
  4. }
- (IBAction) textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}

这两个方法都是轻击虚拟键盘上一个键来关闭它。这属于精确操作,而手指不像鼠标,做这种操作不容易。因此就UI层面而言,这两个方法都不是最好的方法。 在iphone或ipad屏幕上,虚拟键盘占用的面积大小是有限的。通过轻击虚拟键盘之外的区域而关闭虚拟键盘。

第三种方法,通过轻击键盘之外的空白区域关闭虚拟键盘。 在birdNameInput所属的视图控制器类的viewDidLoad方法中定义一个UITapGestureRecognizer的对象,然后将它赋值为它的视图。

  1. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]   initWithTarget:self action:@selector(dismissKeyboard)];
  2. [self.view addGestureRecognizer:tap];
  3. [tap release];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]   initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];

再定义一下选择器调用的方法dismissKeyboard。

  1. -(void)dismissKeyboard {
  2. [birdNameInput resignFirstResponder];
  3. }
-(void)dismissKeyboard {
[birdNameInput resignFirstResponder];
}

如果屏幕上有多个textField的话,一个一个地列出来就有些麻烦。那么将方法修改一下,如下:

  1. -(void)dismissKeyboard {
  2. NSArray *subviews = [self.view subviews];
  3. for (id objInput in subviews) {
  4. if ([objInput isKindOfClass:[UITextField class]]) {
  5. UITextField *theTextField = objInput;
  6. if ([objInput isFirstResponder]) {
  7. [theTextField resignFirstResponder];
  8. }
  9. }
  10. }
  11. }
-(void)dismissKeyboard {
NSArray *subviews = [self.view subviews];
for (id objInput in subviews) {
if ([objInput isKindOfClass:[UITextField class]]) {
UITextField *theTextField = objInput;
if ([objInput isFirstResponder]) {
[theTextField resignFirstResponder];
}
}
}
}

如果这个屏幕上的视图对象很复杂的话,另当别论。 这个方法是编码新建一个手势对象。也可以直接使用interface builder图形化开发工具,在storyboard中拉入一个手势对象到视图控制器类中,再将此手势对象建立一个IBACTION,名称可以是dismissKeyboard。
第四种方法,通过轻击键盘之外的空白区域关闭虚拟键盘。 将屏幕上的view也就是textField的父视图拖一个touch down事件出来,和一个能关闭虚拟键盘的方法连接。如果视图没有touch down事件,可将view的父类从UIView修改为UIButton。 首先定义并实现一个方法backgroundTap:。

  1. - (IBAction) backgroundTap:(id)sender
  2. {
  3. NSArray *subviews = [self.view subviews];
  4. for (id objInput in subviews) {
  5. if ([objInput isKindOfClass:[UITextField class]]) {
  6. UITextField *theTextField = objInput;
  7. if ([objInput isFirstResponder]) {
  8. [theTextField resignFirstResponder];
  9. }
  10. }
  11. }
  12. }
- (IBAction) backgroundTap:(id)sender
{
NSArray *subviews = [self.view subviews];
for (id objInput in subviews) {
if ([objInput isKindOfClass:[UITextField class]]) {
UITextField *theTextField = objInput;
if ([objInput isFirstResponder]) {
[theTextField resignFirstResponder];
}
}
}
}

然后选择背景视图的Touch Down事件,连接 backgroundTap:即可。这样只要轻击一下虚拟键盘之外的区域,就能关闭虚拟键盘。这些方法都是使用resignFirstResponder方法来关闭虚拟键盘,还有其他的方法。

第五种方法,使用endEditing:方法 在所在的视图控制器类中,覆盖这个方法。

  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  2. [[self view] endEditing:YES];
  3. }
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self view] endEditing:YES];
}

This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign. 但是,如果这个屏幕很复杂,虚拟键盘之外的区域中有很多按钮。轻击这些区域时可能会轻击到这些按钮,这样虚拟键盘就不能关闭。 要是找到一个没有按钮的空白区域都不容易且还有隐藏的视图对象时,通过轻击虚拟键盘之外的区域关闭虚拟键盘的方法实现起来就难了。

第六种方法,覆盖hitTest:withEvent:方法关闭虚拟键盘

在stackoverflow.com上,有人这样总结。说使用hitTest:withEvent:方法是最好的,也是最容易的解决方法。

I think the easiest (and best) way to do this is to subclass your global view and use hitTest:withEvent method to listen to any touch. Touches on keyboard aren't registered, so hitTest:withEvent is only called when you touch/scroll/swipe/pinch... somewhere else, then call [self endEditing:YES]. This is better than using touchesBegan because touchesBegan are not called if you click on a button on top of the view. It is better than UITapGestureRecognizer which can't recognize a scrolling gesture for example. It is also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen every where. Moreover, it doesn't block other actions, you don't need to tap twice to select a button outside (like in the case of a UIPopover). Also, it's better than calling [textField resignFirstResponder], because you may have many text fields on screen, so this works for all of them.

因此,我再建立一个继承UIView的视图类。在这个视图类中,覆盖hitTest:withEvent:方法,增加[self endEditing:YES]方法。

  1. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  2. UIView *result = [super hitTest:point withEvent:event];
  3. [self endEditing:YES]
  4. return result;
  5. }
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *result = [super hitTest:point withEvent:event];
[self endEditing:YES]
return result;
}

我将视图控制器的主视图所属类修改为这个新建视图类。这样在屏幕上轻击任何位置都会关闭虚拟键盘。 这个方法是最简单,也是最好的关闭虚拟键盘的方法。 使用好hitTest:withEvent:这个方法,还可以实现很多很复杂的功能。 The implementation of hitTest:withEvent: in UIResponder does the following:

  • It calls pointInside:withEvent: of self
  • If the return is NO, hitTest:withEvent: returns nil. the end of the story.
  • If the return is YES, it sends hitTest:withEvent: messages to its subviews. it starts from the top-level subview, and continues to other views until a subview returns a non-nil object, or all subviews receive the message.
  • If a subview returns a non-nil object in the first time, the first hitTest:withEvent: returns that object. the end of the story.
  • If no subview returns a non-nil object, the first hitTest:withEvent: returns self

This process repeats recursively, so normally the leaf view of the view hierarchy is returned eventually. However, you might override hitTest:withEvent to do something differently. In many cases, overriding pointInside:withEvent: is simpler and still provides enough options to tweak event handling in your application.

关闭ios虚拟键盘的几种方法的更多相关文章

  1. (转载)ios关闭虚拟键盘的几种方法

    在iOS应用开发中,有三类视图对象会打开虚拟键盘,进行输入操作,但如何关闭虚拟键盘,却没有提供自动化的方法.这个需要我们自己去实现.这三类视图对象分别是UITextField,UITextView和U ...

  2. 【转】iOS 上常用的两个功能:点击屏幕和return退出隐藏键盘和解决虚拟键盘挡住UITextField的方法

    iOS上面对键盘的处理很不人性化,所以这些功能都需要自己来实现, 首先是点击return和屏幕隐藏键盘 这个首先引用双子座的博客 http://my.oschina.net/plumsoft/blog ...

  3. IOS 点击空白处隐藏键盘的几种方法

    IOS 点击空白处隐藏键盘的几种方法     IOS7 点击空白处隐藏键盘的几种方法   IOS开发中经常要用到输入框,默认情况下点击输入框就会弹出键盘,但是必须要实现输入框return的委托方法才能 ...

  4. IOS7 点击空白处隐藏键盘的几种方法

    IOS7 点击空白处隐藏键盘的几种方法   iOS开发中经常要用到输入框,默认情况下点击输入框就会弹出键盘,但是必须要实现输入框return的委托方法才能取消键盘的显示,对于用户体验来说很不友好,我们 ...

  5. iOS 收起键盘的几种方式

    iOS 收起键盘的几种方式 1.一般的view上收起键盘 // 手势 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ ...

  6. iOS拨打电话(三种方法)

    iOS拨打电话(三种方法)  查了很多地方的关于iOS程序拨打电话,大都不全,今天我总结了三种方法,各有不同,拿来给大家分享,希望给大家有所帮助 1,这种方法,拨打完电话回不到原来的应用,会停留在通讯 ...

  7. 48-设置tomcat虚拟路径的两种方法(Eclipse、tomcat、IDEA)

    设置tomcat虚拟路径的两种方法(Eclipse.tomcat.IDEA) 三种方式设置虚拟服务器路径如果我们要实现一个上传文件的功能,但是又想要上传的文件不会随着自己web服务器的重启而不能访问了 ...

  8. ipa包如何打包?ios打包ipa的四种方法分享

      今天带来的内容是ios打包ipa的四种方法.总结一下,目前.app包转为.ipa包的方法有以下几种,下面一起来看看吧!    1.Apple推荐的方式,即实用xcode的archive功能 Xco ...

  9. 关于cocos2d-x 中 CCEditBox 的输入位置和IOS虚拟键盘位置不重合的bug

    这个文章的名字起的实在是有点长,主要是怕说不清楚. 在IOS上,输入时,我看到过的比较少,就两种,如附件两张图.一个是虚拟键盘的输入框完全是在CCEditBox上,另一张虚拟键盘的输入区域是紧挨着键盘 ...

随机推荐

  1. [__NSCFNumber length]: unrecognized selector sent to instance 0x8b3c310

    出现这种问题一般是你把int类型的数值赋给了NSString. 比如: 你定义了一个NSString类型的属性sex,但是服务端返回的sex字段实际上是NSNumber类型, 你直接把NSNumber ...

  2. Wonderful Sentense

    1.Sorry if I might sound arrogant or offensive. 2.Any further question? 3.How dare you! 4.Try it if ...

  3. Ajax实现聊天

    用Ajax发送请求,查询数据库是否有自己的数据,如果有自己的数据,就返回 前端页面 <head> <meta charset="UTF-8"> <ti ...

  4. jQuery之选择器

    jQuery元素选择器和属性选择器允许您通过标签名.属性名或内容对 HTML 元素进行选择和操作,而在 HTML DOM中,选择器可以对DOM元素组或单个DOM 节点进行操作.通俗点说,选择器的作用就 ...

  5. 几款jQuery右键菜单插件

    1.jQuery Very Simple ContextMenu Plugin 2.ContextJS Project Page:http://lab.jakiestfu.com/contextjs/ ...

  6. 【Unity3D】Unity3D之 注册表动态存取游戏存档——PlayerPrefs类

    [Unity3D]Unity3D之 注册表动态存取游戏存档--PlayerPrefs类 1.Unity3D提供了一个用于本地持久化保存与读取的类--PlayerPrefs.工作原理非常简单,以键值对的 ...

  7. 20150224—ASP.NET基础

    一.如何使用VS2012创建ASP.NET的项目. 文件-新建-网站 出现以下对话框,选择ASP.NET的空网站(注意,左侧使用的模板是Visual C#) 选择好存放位置,名字之后 点击确定.这样就 ...

  8. 20140912-关于.NET技术体系的思维导图

    逛园子时看到的. 关于.NET技术体系的思维导图

  9. (转)文件系统缓存dirty_ratio与dirty_background_ratio两个参数区别

    这两天在调优数据库性能的过程中需要降低操作系统文件Cache对数据库性能的影响,故调研了一些降低文件系统缓存大小的方法,其中一种是通过修改/proc/sys/vm/dirty_background_r ...

  10. (转)Centos5.5安装MONO2.10.8和Jexus 5.0开启Linux平台.net应用新篇章

    注:本文只做本人记录使用,也可供大家参考,有兴趣的可以一起讨论. 安装步骤 1.yum –y update 2.安装Mono源码安装需要的库 yum -y install gcc gcc-c++ bi ...