繁体   English   中英

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

[英]iOS - Dismiss keyboard when touching outside of UITextField

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

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

编码:

在视图中DidLoad

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

[self.view addGestureRecognizer:tap];

在解雇键盘中:

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

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

Swift 3版本看起来像那样

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

对于解雇键盘

@objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}

我混搭了几个答案。

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

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

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

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

或者

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

https://github.com/michaeltyson/TPKeyboardAvoiding

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

[tap setCancelsTouchesInView:NO];

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

在此处阅读该property (搜索CancelsTouchesInView ): UIGestureRecognizer Class Reference

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

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

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

斯威夫特 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
    }
}

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

override func viewDidLoad() {
    super.viewDidLoad()

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

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

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

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

目标-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

斯威夫特 4 单线

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

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

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

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

这一定是通过触摸外部来隐藏键盘的最简单方法:

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

(来自如何在用户点击文本字段外的其他区域时关闭键盘?

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

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

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

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

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


创建隐藏键盘的动作

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

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>

- (IBAction)dissmissKeyboardOnTap:(id)sender;

@end

然后把这个添加到同一个ViewController的实现文件中:

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

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

在此处输入图片说明


将动作与用户事件挂钩

现在您需要将此操作与触摸键盘的用户手势相关联。

重要 - 您需要将故事板中包含的“UIView”转换为 UIControl ,以便它可以接收事件。 从您的视图控制器场景层次结构中选择视图:

在此处输入图片说明

...并改变它的类:

在此处输入图片说明

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

在此处输入图片说明

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

(注意:要将动作与事件挂钩,您还可以将接收到的动作直接拖到视图控制器层次结构中的 UIControl 上。它在层次结构中显示为“控件”。)

如果我猜对了,您想通过点击textfield outSide 来退出键盘,但您没有textfield参考。

尝试这个;

  • 取全局 textField,我们称之为reftextField
  • 现在在textFieldDidBeginEditing中将引用的文本字段设置为

    - (void) textFieldDidBeginEditing:(UITextField *)textField{ reftextField = textField; }
  • 现在您可以愉快地在任何按钮时钟上使用,(建议在开始编辑时添加透明按钮)

     - (void)dismissKeyboard { [reftextField resignFirstResponder]; }
  • 或者对于辞职完成按钮试试这个。

     //for resigning on done button - (BOOL) textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; return YES; }

只是在这里添加到列表中,我的版本是如何在外部触摸时关闭键盘。

视图加载:

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

任何地方:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    [textFieldName resignFirstResponder];
    puts("Dismissed the keyboard");
}

这里有很多关于使用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);
}

这不是最强大的解决方案,但对我有用。

目标-C:

在您的ViewController.m文件中添加此代码:

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

迅速:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}

您可以为 UiView 创建类别并按如下方式覆盖 touchesBegan 主菜单。

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

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

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

@Jensen2k 答案的 Swift 版本:

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:"))

在 swift 5 中,您可以使用以下代码关闭文本字段外的键盘

override func viewDidLoad() {
    // ... code

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

@objc func dismissKeyboard(_ sender: UITapGestureRecognizer) {
    self.view.endEditing(true)
}

我在这里尝试了许多响应,但都没有运气。 我的点击手势识别器总是导致我的UIButtons在点击时没有响应,即使我将手势识别器的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执行只是一些事情......

我在新开发中使用了 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];
}

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

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

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

     }
}

这有效

在这个例子中,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");
}
- (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];

}

您可以使用 UITapGestureRecongnizer 方法通过在 UITextField 外部单击来关闭键盘。 每当用户在 UITextField 之外单击时使用此方法,键盘就会被关闭。 下面是使用它的代码片段。

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

    [self.view addGestureRecognizer:tap];


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

}

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

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.
    }
}

你的故事板看看那个就像。

在此处输入图片说明

  • 在视图中设置文本字段委托加载:

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

     func textFieldShouldReturn(userText: UITextField!) -> Bool { userText.resignFirstResponder() return true; } 

将消息resignFirstResponder发送到放置它的文本文件。 参阅此帖子以获取更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM