消除键盘的简单方法?


376

我有很多控件散布在表中的许多表格单元格中,我想知道是否有一种更简便的方法来关闭键盘,而不必遍历所有控件并将它们全部放弃为第一响应者。我想问题是..我怎样才能使当前的第一响应键盘?



请注意以下所有答案。如果您在KB辞职后立即执行Segue,则KB Get会变成孤立的,并且不能被取消。您必须在textFieldShouldReturn方法中关闭KB。
gjpc 2014年

26
全球键盘解雇的正确方法:[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
Yerk

我发现此视频对pinkstone.co.uk/…很有帮助 。也许它可以帮助别人。
狂热爱好者

Answers:


796

尝试:

[self.view endEditing:YES];

1
这似乎确实有效(在ios4.1上测试)。虽然仅在iOS 3.2或更高版本中可用。我不确定这是否真的可以保证有效,或者只是以未证明有效的方式调用API的非保证性副作用。
JosephH 2010年

3
这对我来说非常有效,并且肯定比该问题的其他答案更好。文档说它在iOS 2.0及更高版本中可用。
antyawn 2010年

8
正如文档所述:“此方法查看当前视图及其子视图层次结构中当前是第一响应者的文本字段。如果找到该方法,它将要求该文本字段辞去第一响应者的角色。如果设置了force参数如果为是,则永远不会询问该文本字段;它被迫辞职。” -因此这是IMO对原始问题的正确答案(用例:我有一个包含数百万个字段的表单,嗯-十个……大概,我需要关闭键盘)。
joshis 2011年

14
答案没有错,但有一点不对,实际上应该是:[self.view endEditing:YES];因为在Objective-C中BOOL值为YES / NO。
克里斯本

24
克里斯本:您可以使用YES / NO,TRUE / FALSE,0/1。
Michael Superczynski 2013年

126

您可以使用强制当前正在编辑的视图退出其第一响应者状态[view endEditing:YES]。这将隐藏键盘。

与不同-[UIResponder resignFirstResponder]-[UIView endEditing:]将在子视图中搜索以找到当前的第一响应者。因此,您可以将其发送到顶级视图(例如self.view在中UIViewController),它将做正确的事情。

(此答案先前包含了其他一些解决方案,这些解决方案也可以使用,但比必需的解决方案更为复杂。为了避免混淆,我删除了它们。)


但这只会阻止组件成为firstResponder,而不会从元素中删除当前的firstResponder状态。
Kendall Helmstetter Gelner 09年

我的意思是重写成为FirstResponder来将第一个响应者存储在某个地方,以便以后可以访问它(在这种情况下,请辞职)。基本问题是Cocoa Touch无法提供询问窗口或查看其第一响应者的方法。
尼古拉斯·莱利

+1添加beginFirstResponder解决了我在其他UITextField上轻拍时遇到的问题。
杰森·乔治

3
这已经过时了。的[self.view endEditing:YES];回答是好。
ftvs 2012年

1
这不是过时的,这个答案确切地解释了如何[UIView endediting:]工作。在我开发的一个应用程序中,在UINavigationViewController中添加了一个搜索框,如果您只是调用[self.view endEditing:YES],作为self视图控制器,则此方法将不起作用,而是直接在添加了搜索框的视图范围中调用此方法,例如:[self.mySearchBoxView endEditing:YES]
JanCássio15年

92

您可以将零目标操作发送到应用程序,它会随时辞职第一响应者,而不必担心当前哪个视图具有第一响应者状态。

目标C:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

Swift 3.0:

UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, from: nil, for: nil)

在Mac OS X上,菜单命令通常没有针对性的操作,这在iOS上很有用。


14
整个页面的最佳解决方案。
Leo Natan

绝对是从iOS应用中任何地方摆脱键盘的最佳方法。
Ben Sinclair 2014年

仍适用于iOS8。在我的应用程序中,我有一个侧边栏菜单,并且有时“中心”视图控制器会显示键盘。如果要显示侧栏菜单,我想关闭键盘。因此,我将此代码添加到了我的侧栏菜单“类”的viewWillAppear方法中。
珍妮·夏娃

1
仍可在iOS 9中使用。全局取消文本字段焦点和关闭键盘的好方法。
bmjohns

并继续进行此特别的评论。...仍可在iOS 10中使用。:-)
Traveling Man

56

老实说,我对这里提出的任何解决方案都不感到疯狂。我确实找到了一种使用TapGestureRecognizer的好方法,我认为这是问题的核心:单击键盘以外的任何东西时,请关闭键盘。

  1. 在viewDidLoad中,注册以接收键盘通知并创建UITapGestureRecognizer:

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    
    [nc addObserver:self selector:@selector(keyboardWillShow:) name:
    UIKeyboardWillShowNotification object:nil];
    
    [nc addObserver:self selector:@selector(keyboardWillHide:) name:
    UIKeyboardWillHideNotification object:nil];
    
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
    action:@selector(didTapAnywhere:)];
  2. 添加键盘显示/隐藏响应器。您可以在其中添加和删除TapGestureRecognizer到UIView,点击时应关闭键盘。注意:您不必将其添加到所有子视图或控件中。

    -(void) keyboardWillShow:(NSNotification *) note {
        [self.view addGestureRecognizer:tapRecognizer];
    }
    
    -(void) keyboardWillHide:(NSNotification *) note
    {
        [self.view removeGestureRecognizer:tapRecognizer];
    }
  3. TapGestureRecognizer会在您点击时调用您的函数,您可以像这样关闭键盘:

    -(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer {    
        [textField resignFirstResponder];
    }

此解决方案的优点在于,它仅过滤Taps,而不刷卡。因此,如果您在键盘上方滚动内容,滑动仍将滚动并保持键盘显示。通过在键盘移开后移除手势识别器,可以正常处理以后在视图上的点击。


我在@implementation中添加了@property(分配)UITapGestureRecognizer * tapRecognizer; 并修改self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere :)];
托德教授,

我正在尝试做类似的事情,但没有得到回调。好奇:为什么您的财产被“转让”?
塔霍金刚狼2011年

加一,而且这应该是默认的iOS行为。或者至少添加一种简单的方式来切换关闭按钮。
Shaunti Fondrisi 2015年

24

这是一种通过在一个地方添加代码来使键盘return任何文本字段中击中时都消失的解决方案(因此不必为每个文本字段添加处理程序):


考虑这种情况:

我有viewcontroller两个文本字段(用户名和密码)。和viewcontroller实施UITextFieldDelegate协议

我在viewDidLoad中做到这一点

- (void)viewDidLoad 
{
    [super viewDidLoad];

    username.delegate = self;
    password.delegate = self;
}

并且viewcontroller将可选方法实现为

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

不论您处于哪个文本字段,只要我return按键盘,它就会被关闭!

在您的情况下,只要将所有文本字段的委托设置为self并实施 textFieldShouldReturn


好吧,我已经解决了问题,但就我而言,我想自己关闭键盘(以代码形式),而且我不知道哪个textField具有第一响应者状态。
Seventoes

1
在某些情况下,您可能想关闭键盘而不必按“返回”键,例如,当即将显示侧边栏菜单时
Peter Johnson

编辑以澄清此答案在击中“返回”是可以接受的解决方案的情况下才有意义。[就我而言,当用户在正在编辑的字段之外点击时,我也想关闭键盘;此答案无济于事。]
ToolmakerSteve

14

更好的方法是让某些“窃取”第一响应者身份。

由于UIApplication是UIResponder的子类,因此您可以尝试:

[[UIApplication sharedApplication] becomeFirstResponder]
[[UIApplication sharedApplication] resignFirstResponder]

失败的话,创建一个尺寸为零的新UITextField,将其添加到某处的视图中并执行类似的操作(随后是辞职)。


1
UIApplication技巧不起作用(它至少在模拟器上会崩溃),但是您不需要大小为零的UITextField-只需选择任意随机字段并对其进行处理即可。NSResponder的beginFirstResponder是仅通知方法,而UIResponder则不是(实际上设计较差)。
尼古拉斯·莱利

1
啊哈,谢谢!在UIApplication上调用它会崩溃,但是零尺寸的UITextField效果很好,而且我不必检索任何以前的字段。
2009年

如果有官方的,完善的和有据可查的方法,为什么有人会这样做呢?
Maciej Swic

2
他们不会,但是大多数人都认为答案是更好的解决方案。当时还不为人所知(我的答案是2009年,另一个答案是2010年以后的一年)。但我留给后代。
Kendall Helmstetter Gelner 2013年

8

将其隐藏在一些实用程序类中。

+ (void)dismissKeyboard {
    [self globalResignFirstResponder];
}

+ (void) globalResignFirstResponder {
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    for (UIView * view in [window subviews]){
        [self globalResignFirstResponderRec:view];
    }
}

+ (void) globalResignFirstResponderRec:(UIView*) view {
    if ([view respondsToSelector:@selector(resignFirstResponder)]){
        [view resignFirstResponder];
    }
    for (UIView * subview in [view subviews]){
        [self globalResignFirstResponderRec:subview];
    }
}

1
这就是我想要的!
aslisabanci 2011年

完美,除了您根本不需要globalResignFirstResponderRec方法外,只需调用[view endEditing:YES]。它做同样的事情。
n13

是的 最终的解决方案!我尝试了很多方法,只有这一方法对我有效!非常感谢你!
杜伊

6

@尼古拉斯·莱利(Nicholas Riley)和@肯德尔·赫尔姆斯特(Kendall Helmstetter)盖恩(Genn)&@cannyboy:

绝对辉煌​​!

谢谢。

考虑到您的建议以及该线程中其他人的建议,这就是我所做的:

使用时的外观:

[[self appDelegate] dismissKeyboard]; (注意:我添加了appDelegate作为NSObject的补充,因此我可以在任何地方使用任何东西)

幕后的样子:

- (void)dismissKeyboard 
{
    UITextField *tempTextField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
    tempTextField.enabled = NO;
    [myRootViewController.view addSubview:tempTextField];
    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
}

编辑

修改我的回答包括在内tempTextField.enabled = NO;。如果您在整个应用程序中都依赖这些通知,则禁用文本字段将阻止UIKeyboardWillShowNotificationUIKeyboardWillHideNotification发送键盘通知。


我不知道它是否有效,但这似乎是一种聪明而简单的方法。
妖魔

5

关于用户在UITextField或键盘之外的屏幕上的任意位置触摸时如何关闭iOS中的键盘的快速提示。考虑到iOS键盘会占用多少空间,采用一种简单直观的方式让用户关闭键盘是很有意义的。

这是一个链接


大!添加到AppDelegate使其适用于所有相关视图。
赵九龙

5

这里有很多过于复杂的答案,可能是因为在iOS文档中不容易找到答案。JosephH在上面具有它:

[[view window] endEditing:YES];

4

比Meagar的答案更简单

覆写 touchesBegan:withEvent:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [textField resignFirstResponder];`
}

这将dismiss the keyboard当你在任何地方触及background


3

这是我在代码中使用的内容。它就像一个魅力!

在yourviewcontroller.h中添加:

@property (nonatomic) UITapGestureRecognizer *tapRecognizer;

现在在.m文件中,将其添加到您的ViewDidLoad函数中:

- (void)viewDidLoad {
    //Keyboard stuff
    tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAnywhere:)];
    tapRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapRecognizer];
}

另外,在.m文件中添加以下功能:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}

谢谢!但是您应该将函数重命名为'didTapAnywhere'或将手势识别器重命名为'handleSingleTap';-)
Matthijs

2

在视图控制器的头文件中,添加<UITextFieldDelegate>到控制器接口的定义,以使其符合UITextField委托协议...

@interface someViewController : UIViewController <UITextFieldDelegate>

...在控制器的实现文件(.m)中,添加以下方法,如果您已经具有viewDidLoad方法,则在其中添加代码...

- (void)viewDidLoad
{
    // Do any additional setup after loading the view, typically from a nib.
    self.yourTextBox.delegate = self;
}

...然后,将yourTextBox链接到您的实际文本字段

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField 
{
    if (theTextField == yourTextBox) {
        [theTextField resignFirstResponder];
    }
    return YES;
}

2

您应该将发送endEditing:到工作窗口的子类UIView

[[UIApplication sharedApplication].windows.firstObject endEditing:NO];

我敢打赌,您的意思是“是”)
Matrosov Alexander


2

在Swift 3中,您可以执行以下操作

UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

1

杰里米(Jeremy)的答案对我而言并不奏效,因为我在选项卡视图中有一个导航堆栈,在其顶部有一个模式对话框。我现在正在使用以下产品,它正在为我工​​作,但是您的行驶里程可能会有所不同。

 // dismiss keyboard (mostly macro)
[[UIApplication sharedApplication].delegate dismissKeyboard]; // call this in your to app dismiss the keybaord

// --- dismiss keyboard (in indexAppDelegate.h) (mostly macro)
- (void)dismissKeyboard;

// --- dismiss keyboard (in indexAppDelegate.m) (mostly macro)
// do this from anywhere to dismiss the keybard
- (void)dismissKeyboard {    // from: http://stackoverflow.com/questions/741185/easy-way-to-dismiss-keyboard

    UITextField *tempTextField = [[UITextField alloc] initWithFrame:CGRectZero];

    UIViewController *myRootViewController = <#viewController#>; // for simple apps (INPUT: viewController is whatever your root controller is called.  Probably is a way to determine this progragrammatically)
    UIViewController *uivc;
    if (myRootViewController.navigationController != nil) { // for when there is a nav stack
        uivc = myRootViewController.navigationController;
    } else {
        uivc = myRootViewController;
    }

    if (uivc.modalViewController != nil) { // for when there is something modal
        uivc = uivc.modalViewController;
    } 

    [uivc.view  addSubview:tempTextField];

    [tempTextField becomeFirstResponder];
    [tempTextField resignFirstResponder];
    [tempTextField removeFromSuperview];
    [tempTextField release];

}

嗯-为什么要投票?我通过测试代码解决了现实中的特定缺点。我可以理解缺乏投票支持,但将我投票给负面地区实在令人沮丧。我仍然希望以上答案可以帮助其他人。
JJ Rohrer

1

您可能还需要重写UIViewController disablesAutomaticKeyboardDismissal才能使其在某些情况下起作用。如果您有一个,可能必须在UINavigationController上完成。


1

子类化您的文本字段...以及文本视图

在子类中放置此代码。

-(void)conformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissKeyBoard) name:KEYBOARD_DISMISS object:nil];
}

-(void)deConformsToKeyboardDismissNotification{

    [[NSNotificationCenter defaultCenter] removeObserver:self name:KEYBOARD_DISMISS object:nil];
}

- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [self resignFirstResponder];
}

在文本字段委托中(类似于textview委托)

-(void)textFieldDidBeginEditing:(JCPTextField *)textField{
     [textField conformsToKeyboardDismissNotification];
}


- (void)textFieldDidEndEditing:(JCPTextField *)textField{
    [textField deConformsToKeyboardDismissNotification];
}

全部设置好了。现在只需从代码中的任何位置发布通知即可。它将退出任何键盘。


1

我们可以迅速

UIApplication.sharedApplication().sendAction("resignFirstResponder", to: nil, from: nil, forEvent: nil)

我不知道急救人员的工作方式。我该放在哪里?在我的视图控制器或委托?
Shayan C

没关系 您可以将其放置在任何您想要的地方。即按钮动作
Eike

1

要在弹出键盘后关闭键盘,有2种情况

  1. 当UITextField 在UIScrollView内时

  2. 当UITextField 在UIScrollView之外时

2.当UITextField在UIScrollView外部时,覆盖UIViewController子类中的方法

您还必须为所有UITextView添加委托

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
}
  1. 滚动视图中,在外部轻按不会触发任何事件,因此在这种情况下,请使用Tap Gesture Recognizer,为滚动视图拖放UITapGesture为其创建IBAction

要创建IBAction,请按ctrl键并单击UITapGesture并将其拖动到viewcontroller的.h文件中。

在这里,我将tappedEvent命名为我的动作名称

- (IBAction)tappedEvent:(id)sender {
      [self.view endEditing:YES];  }

给定的上述信息来自以下链接,如果您不了解上述数据,请参阅更多信息或与我联系。

http://samwize.com/2014/03/27/dismiss-keyboard-when-tap-outside-a-uitextfield-slash-uitextview/


0

我讨厌没有“私有的”方式来以编程方式关闭键盘而不使用私有API调用。通常,我需要以编程方式关闭键盘,而又不知道哪个对象是第一响应者。我诉诸于self使用Objective-C运行时API 进行检查,枚举其所有属性,提取类型为的属性UITextField,然后将其发送给resignFirstResponder消息。

要做这个不难...


0

这不是很漂亮,但是当我不知道响应者是什么时,我辞职firstResponder的方式是:

在IB中或以编程方式创建UITextField。隐藏它。如果您是在IB中创建的,则将其链接到您的代码。然后,当您想关闭键盘时,将响应器切换到不可见的文本字段,然后立即将其辞职:

  [self.invisibleField becomeFirstResponder];
  [self.invisibleField resignFirstResponder];

0

您可以递归地遍历子视图,存储所有UITextField的数组,然后遍历它们并将其全部签名。

这并不是一个很好的解决方案,特别是如果您有很多子视图时,但是对于简单的应用程序,它应该可以解决问题。

我以更复杂但更高效的方式解决了这个问题,但是使用单例/管​​理器作为应用程序的动画引擎,并且每当文本字段成为响应者时,我都会将其分配给静态对象,这样可以得到基于某些其他事件而被清扫(辞职)……对于我来说,在段落中几乎无法解释。

有创造力,发现问题后,我只花了10分钟就为我的应用程序思考了一下。


这个月前解决了;)我最终只是将活动字段保存为焦点并使用了它。
Seventoes 2010年

0

我最近需要使用一种更健壮的方法:

- (void) dismissKeyboard {
    NSArray *windows = [UIApplication sharedApplication].windows;

    for(UIWindow *window in windows) [window endEditing:true];

    //  Or if you're only working with one UIWindow:

    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

我发现其他一些“全局”方法不起作用(例如,UIWebViewWKWebView拒绝辞职)。


0

在视图中添加一个Tap Gesture Recognizer,并对其进行定义

您的.m文件会像

    - (IBAction)hideKeyboardGesture:(id)sender {
    NSArray *windows = [UIApplication sharedApplication].windows;
    for(UIWindow *window in windows) [window endEditing:true];
    [[UIApplication sharedApplication].keyWindow endEditing:true];
}

对我有用


0

是的,endEditing是最好的选择。从iOW 7.0起,它UIScrollView具有一项很酷的功能,可以在与滚动视图进行交互时关闭键盘。为此,您可以设置keyboardDismissMode属性UIScrollView

将键盘关闭模式设置为:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag

它具有其他几种类型。看看这个苹果文件



0

简便的方法是调用方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    if(![txtfld resignFirstResponder])
    {
        [txtfld resignFirstResponder];
    }
    else
    {

    }
    [super touchesBegan:touches withEvent:event];
}

您不需要那里的“如果”,无论如何resignFirstResponder都会这样做。也许您是说-(BOOL)canResignFirstResponder?
Seventoes 2010年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.