cocoa touch - iOS - 在UITextField外部触摸时关闭键盘

我想知道当用户触摸UITextField之外时如何使键盘消失。

30个解决方案
722 votes

您需要添加一个UITapGestureRecogniser并将其分配给视图,然后在其选择器上的aTextField上调用resign first responder。

代码:

在viewDidLoad中

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];

[self.view addGestureRecognizer:tap];

在dismissKeyboard中:

-(void)dismissKeyboard 
{
    [aTextField resignFirstResponder];
}

(其中aTextField是负责键盘的文本字段)

Swift 3版本看起来像那样

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)

对于dismissKeyboard

func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}
Jensen2k answered 2019-01-06T22:03:08Z
168 votes

我捣乱了几个答案。

使用在viewDidLoad:期间初始化的ivar

UIGestureRecognizer *tapper;

- (void)viewDidLoad
{
    [super viewDidLoad];
    tapper = [[UITapGestureRecognizer alloc]
                initWithTarget:self action:@selector(handleSingleTap:)];
    tapper.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapper];
}

关闭当前正在编辑的内容:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}
drewish answered 2019-01-06T22:03:43Z
100 votes

检查一下,这将是最简单的方法,

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
      [self.view endEditing:YES];// this will do the trick
}

要么

该库将处理包括滚动条自动滚动,点击空间以隐藏键盘等...

[https://github.com/michaeltyson/TPKeyboardAvoiding]

Prasad De Zoysa answered 2019-01-06T22:04:21Z
83 votes

我看到有些人在使用property方法时遇到问题。 我完成此功能的最简单方法是在保持现有按钮的点击行为不变的情况下,只添加一行@ Jensen2k的答案:

[tap setCancelsTouchesInView:NO];

这允许我现有的按钮仍然可以使用@Dmitry Sitnikov的方法。

在这里阅读property(搜索CancelsTouchesInView):UIGestureRecognizer类参考

我不确定它如何与滚动条一起工作,因为我看到一些问题,但希望其他人可能遇到我的相同情况。

Qiao Yi answered 2019-01-06T22:05:02Z
55 votes

最好将UIView作为UIControl的实例(在界面构建器中),然后将它们的TouchUpInside事件连接到dismissKeyboard方法。 此IBAction方法将如下所示:

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}
Dmitry Sitnikov answered 2019-01-06T22:05:24Z
26 votes

Swift版本,这与其他元素(如UIButton或其他UITextField)结合使用:

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}
Rob answered 2019-01-06T22:05:46Z
15 votes

怎么样:我知道这是一个老帖子。 它可能会帮助一些人:)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    NSArray *subviews = [self.view subviews];
    for (id objects in subviews) {
        if ([objects isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objects;
            if ([objects isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        } 
    }
}
Mr H answered 2019-01-06T22:06:08Z
13 votes

这是一个很好的通用解决方案:

Objective-C的:

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

迅速:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

基于@icodebuster解决方案:[https://stackoverflow.com/a/18756253/417652]

eduludi answered 2019-01-06T22:06:40Z
10 votes

我认为最简单(也是最好)的方法是将您的全局视图子类化并使用[textField resignFirstResponder]方法来监听任何触摸。 键盘上的触摸未注册,因此只有在触摸/滚动/滑动/捏合...其他地方时,才会调用hitTest:withEvent,然后调用touchesBegan

这比使用[textField resignFirstResponder]更好,因为如果单击视图顶部的按钮,则不会调用touchesBegan。 例如,它不能识别滚动手势的UITapGestureRecognizer。 它也比使用昏暗的屏幕更好,因为在复杂和动态的用户界面中,你无法在任何地方放置昏暗的屏幕。 此外,它不会阻止其他操作,您不需要点击两次以选择外部按钮(如UIPopover的情况)。

此外,它比调用[textField resignFirstResponder]更好,因为屏幕上可能有许多文本字段,因此这适用于所有这些字段。

Enzo Tran answered 2019-01-06T22:07:16Z
9 votes

斯威夫特4

使用此扩展方法设置NavigationBar,例如viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupHideKeyboardOnTap()
}

即使点击NavigationBar,键盘也会被解雇。

import UIKit
extension UIViewController {
    /// Call this once to dismiss open keyboards by tapping anywhere in the view controller
    func setupHideKeyboardOnTap() {
        self.view.addGestureRecognizer(self.endEditingRecognizer())
        self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer())
    }

    /// Dismisses the keyboard from self.view
    private func endEditingRecognizer() -> UIGestureRecognizer {
        let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:)))
        tap.cancelsTouchesInView = false
        return tap
    }
}
FBente answered 2019-01-06T22:07:46Z
6 votes

您可以使用XCode 6及更高版本中的Storyboard执行此操作:


创建隐藏键盘的操作

将其添加到ViewController使用的类的头文件中:

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>

- (IBAction)dissmissKeyboardOnTap:(id)sender;

@end

然后将其添加到同一ViewController的实现文件中:

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

这将是您的故事板场景(即ViewController)的“已接收操作”之一:

enter image description here


将操作连接到用户事件

现在,您需要将此操作连接到触摸键盘的用户手势。

重要 - 您需要将故事板中包含的'UIView'转换为UIControl,以便它可以接收事件。 从View Controller Scene层次结构中选择视图:

enter image description here

...并改变它的类:

enter image description here

现在从场景的“已接收动作”旁边的小圆圈拖动到场景的“空”部分(实际上是将“已接收动作”拖动到UIControl)。 您将看到一系列可以将您的操作连接到的事件:

enter image description here

选择“内部修饰”选项。 您现在已将您创建的IBAction挂钩到用户触摸键盘的操作。 当用户轻敲键盘时,它现在将被隐藏。

(注意:要将操作挂钩到事件,您还可以将接收到的操作直接拖到View Controllers层次结构中的UIControl上。它在层次结构中显示为“Control”。)

Chris Halcrow answered 2019-01-06T22:09:19Z
6 votes

这必须是通过触摸外部隐藏键盘的最简单方法:

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

(当用户点击文本域外的其他区域时,如何关闭键盘?)

Maggie Phillips answered 2019-01-06T22:09:47Z
5 votes

如果我让你正确,你想要在textfield的外面点击键盘wile,但你没有参考你的textfield

试试这个;

  • 拿全局textField,我们称之为//for resigning on done button - (BOOL) textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; return YES; }
  • 现在在//for resigning on done button - (BOOL) textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; return YES; } 中设置引用文本字段

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
  • 现在您可以愉快地使用任何按钮时钟,(在开始编辑时添加透明按钮推荐)

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
  • 或者对于辞职完成按钮试试这个。

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
rptwsthi answered 2019-01-06T22:10:50Z
5 votes

如果视图完全嵌入在UIScrollView中,那么您可以使用以下内容:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

前者将在滚动表格视图时将键盘设置为关闭屏幕,后者将像股票消息应用程序一样隐藏键盘。

请注意,这些可在iOS 7.0或更高版本上使用。

Joe Masilotti answered 2019-01-06T22:11:25Z
3 votes

只是在这里添加我的版本如何在外部触摸时解除键盘。

viewDidLoad中:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];

任何地方:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    [textFieldName resignFirstResponder];
    puts("Dismissed the keyboard");
}
John Riselvato answered 2019-01-06T22:12:00Z
3 votes

这里有很多关于使用UITapGestureRecognizer的好答案 - 所有这些都打破了UITextField的清除(X)按钮。 解决方案是通过其委托来抑制手势识别器:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]];
    BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]];
    return !(touchViewIsButton && touchSuperviewIsTextField);
}

它不是最强大的解决方案,但它适用于我。

skedastik answered 2019-01-06T22:12:28Z
3 votes

您可以为UiView创建类别并覆盖touchesBegan meathod,如下所示。

它对我来说很好。它是这个问题的集中解决方案。

#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.window endEditing:true];
    [super touchesBegan:touches withEvent:event];
}
@end
Hiren answered 2019-01-06T22:12:56Z
3 votes

Swift版@ Jensen2k的答案:

let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)

func dismissKeyboard() {
    aTextField.resignFirstResponder()
}

一个班轮

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
Syed Asad Ali answered 2019-01-06T22:13:24Z
2 votes

我用Barry的例子来说明我的新发展。 它工作得很好! 但我必须稍微改变,只需要为正在编辑的文本字段解除键盘。

所以,我向Barry添加了以下示例:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    _textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
    _textBeingEdited = nil;
}

另外,我更改了hideKeyboard方法如下:

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    //UITextField * tf = (UITextField *) sender;
    [_textBeingEdited resignFirstResponder];
}
mtorre answered 2019-01-06T22:13:59Z
2 votes

最简单和最简短的方法之一是将此代码添加到您的viewDidLoad

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];
Sudhin Davis answered 2019-01-06T22:14:21Z
2 votes

Swift 4 oneliner

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
newDeveloper answered 2019-01-06T22:14:43Z
1 votes

将消息resignFirstResponder发送到将其放在那里的文本字段。 有关更多信息,请参阅此帖子。

Ke Sun answered 2019-01-06T22:15:05Z
1 votes

这很有效

在这个例子中,aTextField是唯一的UITextField ....如果有其他人或UITextViews,还有更多的事要做。

// YourViewController.h
// ...
@interface YourViewController : UIViewController /* some subclass of UIViewController */ <UITextFieldDelegate> // <-- add this protocol
// ...
@end

// YourViewController.m

@interface YourViewController ()
@property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer;
@end
// ...

@implementation
@synthesize singleTapRecognizer = _singleTapRecognizer;
// ...

- (void)viewDidLoad
{
    [super viewDidLoad];
    // your other init code here
    [self.view addGestureRecognizer:self.singleTapRecognizer];

{

- (UITapGestureRecognizer *)singleTapRecognizer
{
    if (nil == _singleTapRecognizer) {
        _singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)];
        _singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events.
    }
    return _singleTapRecognizer;
}

// Something inside this VC's view was tapped (except the navbar/toolbar)
- (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender
{
    NSLog(@"singleTap");
    [self hideKeyboard:sender];
}

// When the "Return" key is pressed on the on-screen keyboard, hide the keyboard.
// for protocol UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    NSLog(@"Return pressed");
    [self hideKeyboard:textField];
    return YES;
}

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    [aTextField resignFirstResponder];
    NSLog(@"keyboard hidden");
}
Barry answered 2019-01-06T22:15:33Z
1 votes

我在这里尝试了很多回复并没有运气。 我的点击手势识别器总是导致我的UIButton在点击时没有响应,即使我将手势识别器的cancelsTouchesInView属性设置为NO。

这最终解决了这个问题:

有一个伊娃:

UITapGestureRecognizer *_keyboardDismissGestureRecognizer;

当文本字段开始编辑时,设置手势识别器:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    if(_keyboardDismissGestureRecognizer == nil)
    {
        _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)] autorelease];
        _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;

        [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
    }
}

然后诀窍在于你如何设置dismissKeyboard方法:

- (void) dismissKeyboard
{
    [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}

- (void) dismissKeyboardSelector
{
    [self.view endEditing:YES];

    [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
    _keyboardDismissGestureRecognizer = nil;
}

我想有一些关于从触摸处理执行堆栈中获取dismissKeyboardSelector执行的东西......

user1021430 answered 2019-01-06T22:16:27Z
1 votes
- (void)viewDidLoad
{
    [super viewDidLoad]; 

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                                                          initWithTarget:self
                                                          action:@selector(handleSingleTap:)];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
    [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer];

    [self.view addGestureRecognizer:singleTapGestureRecognizer];
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    [self.view endEditing:YES];
    [textField resignFirstResponder];
    [scrollView setContentOffset:CGPointMake(0, -40) animated:YES];

}
Gaurav Gilani answered 2019-01-06T22:16:42Z
1 votes

在ViewController.m文件中添加以下代码:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
aashish tamsya answered 2019-01-06T22:17:04Z
1 votes
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
     view.endEditing(true)

     }
}
Phani Sai answered 2019-01-06T22:17:19Z
1 votes

在这种情况下,可以使用ScrollView并在ScrollView中添加到TextField,我想点击ScrollView并查看然后关闭键盘。 为了以防万一,我尝试创建示例代码。 像这样,

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:)))
        view.addGestureRecognizer(tapGesture)
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

你的故事板看看就像。

enter image description here

Ravi Dhorajiya answered 2019-01-06T22:17:48Z
1 votes

您可以使用UITapGestureRecongnizer方法通过单击UITextField外部来解除键盘。 通过使用此方法,只要用户在UITextField外部单击,键盘就会被解除。 以下是使用它的代码段。

 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                   initWithTarget:self
                                   action:@selector(dismissk)];

    [self.view addGestureRecognizer:tap];


//Method
- (void) dismissk
{
    [abctextfield resignFirstResponder];
    [deftextfield resignFirstResponder];

}
Nirzar Gandhi answered 2019-01-06T22:18:10Z
1 votes
  • 在视图中设置文本字段委托加载:

    override func viewDidLoad() 
    {
      super.viewDidLoad()
      self.userText.delegate = self
    }
    
  • 添加此功能:

    func textFieldShouldReturn(userText: UITextField!) -> Bool 
    {
     userText.resignFirstResponder()
     return true;
    }
    
seggy answered 2019-01-06T22:18:51Z
translate from https://stackoverflow.com:/questions/5306240/ios-dismiss-keyboard-when-touching-outside-of-uitextfield