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

问题描述 投票:436回答:35

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

ios cocoa-touch uitextfield uikit
35个回答
736
投票

你需要添加一个UITapGestureRecogniser并将其分配给视图,然后在它的选择器上调用UITextField上的第一个响应者。

代码:

在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()
}

10
投票

我认为最简单(也是最好)的方法是子类化全局视图并使用hitTest:withEvent方法来聆听任何触摸。键盘上的触摸没有注册,所以hitTest:withEvent仅在你触摸/滚动/滑动/捏合...其他地方时调用,然后调用[self endEditing:YES]

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

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


7
投票

Swift 4 oneliner

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))

6
投票

您可以使用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”。)


6
投票

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

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

(来自How to dismiss keyboard when user tap other area outside textfield?


5
投票

如果我找到了你,你想要在textfield的侧面点击键盘wile,但你没有参考你的textfield

试试这个;

  • 拿全球textField,我们称之为reftextField
  • 现在在textFieldDidBeginEditing中设置引用的文本字段 - (void) textFieldDidBeginEditing:(UITextField *)textField{ reftextField = textField; }
  • 现在,您可以愉快地使用任何按钮单击,(在开始编辑推荐时添加透明按钮) qazxsw poi
  • 或者对于辞职完成按钮试试这个。 - (void)dismissKeyboard { [reftextField resignFirstResponder]; }

5
投票

如果视图完全嵌入在//for resigning on done button - (BOOL) textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; return YES; } 中,那么您可以使用以下内容:

UIScrollView

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

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


3
投票

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

viewDidLoad中:

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

任何地方:

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

3
投票

这里有很多关于使用-(void)handleSingleTap:(UITapGestureRecognizer *)sender{ [textFieldName resignFirstResponder]; puts("Dismissed the keyboard"); } 的好答案 - 所有这些都打破了UITapGestureRecognizer的清晰(X)按钮。解决方案是通过其委托来抑制手势识别器:

UITextField

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


3
投票

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

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

- (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);
}

3
投票

Swift版@ Jensen2k的答案:

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

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.window endEditing:true];
    [super touchesBegan:touches withEvent:event];
}
@end

一个班轮

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

func dismissKeyboard() {
    aTextField.resignFirstResponder()
}

171
投票

我捣乱了几个答案。

使用在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];
}

2
投票

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

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

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))

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

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

2
投票

最简单和最简短的方法之一是将此代码添加到您的- (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]; }

viewDidLoad

2
投票

我在这里尝试了很多回复,没有运气。即使我将手势识别器的[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)]]; 属性设置为NO,我的点击手势识别器总是导致我的UIButtons在点击时没有响应。

这最终解决了这个问题:

有一个伊娃:

cancelsTouchesInView

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

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; } 执行的东西......


1
投票

将消息qazxsw poi发送到文本字段。请qazxsw poi获取更多信息。


1
投票

这有效

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

dismissKeyboardSelector

1
投票
resignFirstResponder

1
投票

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

see this post

1
投票
// 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");
}

1
投票

在这种情况下,可以使用ScrollView并添加到ScrollView中的- (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]; } ,我想点击-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } 和View然后关闭键盘。为了以防万一,我尝试创建示例代码。像这样,

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

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

     }
}

你的故事板看看就像。

TextField


1
投票

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

ScrollView

100
投票

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

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

要么

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

https://github.com/michaeltyson/TPKeyboardAvoiding


1
投票
  • 在视图中设置文本字段委托加载: 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

85
投票

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

[tap setCancelsTouchesInView:NO];

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

在这里阅读property(搜索CancelsTouchesInView):UIGestureRecognizer Class Reference

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


55
投票

最好让你的UIView成为UIControl的一个实例(在界面构建器中),然后将他们的TouchUpInside事件连接到dismissKeyboard方法。这个IBAction方法看起来像:

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}

28
投票

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

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}

21
投票

斯威夫特4

使用此扩展方法设置您的UIViewController,例如在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
    }
}

17
投票

怎么样:我知道这是一个老帖子。它可能有助于某人:)

- (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];
            }
        } 
    }
}

14
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.