触摸 UITextField 以外的任何地方时如何关闭键盘(快速)?

Posted

技术标签:

【中文标题】触摸 UITextField 以外的任何地方时如何关闭键盘(快速)?【英文标题】:How to dismiss keyboard when touching anywhere outside UITextField (in swift)? 【发布时间】:2015-11-23 17:47:08 【问题描述】:

我正在开发一个具有 UIViewController 的项目,在视图控制器上,滚动视图上有一个 UIScrollView 和一个 UITextField。 像这样: 在文本字段中输入一些文本并点击文本字段外的任何位置后,我试图关闭键盘并将其隐藏。 我试过以下代码:

override func viewDidLoad() 
    super.viewDidLoad()
    self.textField.delegate = self;


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
    self.view.endEditing(true)

当我在滚动视图之外点击时它对我有用,但是当我点击滚动视图时没有任何反应并且键盘不会隐藏。

在文本字段外点击anywhere时,有什么方法可以关闭键盘? 谢谢

【问题讨论】:

【参考方案1】:

在这种情况下,UITapGesture 作为选项之一。我试图创建示例代码以防万一。像这样,

class ViewController: UIViewController 

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

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let tapGesture = UITapGestureRecognizer(target: self, action: "tap:")
        view.addGestureRecognizer(tapGesture)
    

    func tap(gesture: UITapGestureRecognizer) 
        textField.resignFirstResponder()
    

【讨论】:

感谢它的工作。但我还有另一个问题,我有一个带有 5 个文本字段的视图控制器。有没有一种很好的方法来做同样的事情,而不需要一个一个地为他们调用“resignFirstResponder”方法? 另一个问题,当我点击文本字段外的任何地方时,有什么办法可以关闭键盘吗?例如当我点击一个按钮时? @white-hat 你能把这个问题当作另一个问题来问吗? @WhiteHat 将您的 5 个文本字段放在一个出口集合中。然后创建一个对集合进行迭代并在每个文本字段上调用 ​​resignFirstResponder 的 dismissKeyboard 方法。您可以从手势识别器和按钮操作中调用此方法。 @WhiteHat ViewController.View 可以调用 endEdting【参考方案2】:

我在 Obj-C 中创建了这个方法,无论用户当前在哪里输入,它都会隐藏键盘:

//call this method
+ (void)hideKeyboard 
    //grab the main window of the application
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    //call our recursive method below
    [self resignResponderForView:window];


//our recursive method
+ (void)resignResponderForView:(UIView *)view 
    //resign responder from this view
    //If it has the keyboard, then it will hide the keyboard
    [view resignFirstResponder];
    //if it has no subviews, then return back up the stack
    if (view.subviews.count == 0)
        return;
    //go through all of its subviews
    for (UIView *subview in view.subviews) 
        //recursively call the method on those subviews
        [self resignResponderForView:subview];
    

我希望这可以翻译成 Swift 并且有意义。它可以在应用程序中的任何位置调用,无论您使用什么 VC 或任何东西,它都会隐藏键盘。

【讨论】:

您可能想查看-[UIView endEditing:]【参考方案3】:

转到键盘类型并选择默认或任何您需要的文本字段。然后覆盖一个方法调用它任何你想要的,我通常称之为touchBegins。以下是您忘记添加的内容

super.touchingBegins(touches, withEvent: event)
 

【讨论】:

【参考方案4】:

试试这个,它已经过测试并且可以工作:

适用于 Swift 3.0 / 4.0

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

适用于旧版 Swift

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) 
    self.view.endEditing(true)

【讨论】:

点击 UIScrollView 时这对我不起作用 请注意,这已更改为在 Swift 2 中覆盖 func touchesBegan(touches: Set, withEvent event: UIEvent?) @WhiteHat 查看我上面的答案,了解适用于 ScrollView 的 Swift 3 答案 这个答案也适用于 Swift 4 !!谢谢。 @Hemang 正如@Rao 在对已接受答案的评论中所述,当您拥有 TableView 时,您需要添加 tap.cancelsTouchesInView = false。希望对您有所帮助。【参考方案5】:

我遇到了同样的问题,我终于解决了!

在 Storyboard 中设置 TapGestureRecognizer,然后在 ViewController 中设置 Outlet

@IBOutlet var tapGesture: UITapGestureRecognizer!

然后在你的 ViewController 中设置一个 IBAction

@IBAction func DismissKeyboard(sender: UITapGestureRecognizer)

 self.view.endEditing(true)
 

将这些行添加到您的 viewDidLoad 方法中

override func viewDidLoad()

    super.viewDidLoad()
    self.view.addGestureRecognizer(tapGesture)

它应该可以工作

希望这会有所帮助!

【讨论】:

【参考方案6】:

为 Swift 4 编辑

编辑:添加了@objc。虽然这不是性能的最佳选择,但在有更好的解决方案之前,这里的一个实例应该不会造成太多问题。

在需要与 GestureRecognizer 后面的项目交互时进行了修复。

编辑:感谢@Rao 指出这一点。已添加tap.cancelsTouchesInView = false

这应该有助于您拥有多个 UITextViewUITextField

创建视图控制器的扩展。与尝试使用 .resignFirstResponder() 相比,这对我来说更顺畅,而且麻烦更少

extension UIViewController

    func setupToHideKeyboardOnTapOnView()
    
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(
            target: self,
            action: #selector(UIViewController.dismissKeyboard))

        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    

    @objc func dismissKeyboard()
    
        view.endEditing(true)
    

在 viewDidLoad 中调用self.setupToHideKeyboardOnTapOnView()

【讨论】:

工作精美且优雅。这应该是答案 我不得不在 Swift 4 中添加 @objc funcdismissKeyboard() @MCR 你是对的。我更新了答案以反映这一点,直到找到更明确的方法。 警告:如果您说,同一视图上的 tableView,此代码将阻止单元格点击,并且您的 didSelectRow 不会触发。为了避免这种情况,您需要在 addGestureRecognizer 之前添加 tap.cancelsTouchesInView = false 有谁知道如何防止dismissKeyboard() 被调用,如果点击是在一个嵌入在self 中的UIViewContainer 的视图中完成的?【参考方案7】:

文本域每次触摸都不同,关闭键盘或使用resignfirstresponder

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

 UITouch *touch = [touches anyObject];
 if(![touch.view isMemberOfClass:[UITextField class]]) 
     [touch.view endEditing:YES];
 

【讨论】:

【参考方案8】:

当在输入区域外触摸任意数量的输入项时,此方法有效。

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
        self.view.endEditing(true)
    

【讨论】:

【参考方案9】:

引入点击手势识别器并为其设置和操作。

使用代码:

nameofyourtextfield.resignfirstresponder()

【讨论】:

【参考方案10】:

适用于 ScrollView 的 Swift 3 工作解决方案

class ViewController: UIViewController 

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

    override func viewDidLoad() 
        super.viewDidLoad()

        // The next line is the crucial part
        // The action is where Swift 3 varies from previous versions
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tap(gesture:)))
        self.view.addGestureRecognizer(tapGesture)
    

    func tap(gesture: UITapGestureRecognizer) 
        textField.resignFirstResponder()
    

另一个question 谈到了我引用和使用的这个问题。接受的答案在 Swift 3 中不再有效。当前选择的答案应该是以下答案。

【讨论】:

@JoeBlow 我相信你错了。您应该辞去 textField 的第一响应者的职务。不是景色。我在我当前的项目中有这个代码,只是在一个新项目中测试了它。更不用说,我的答案只是 Pixyzehn 写的答案的更新版本。 嘿,开发者@Devbot10 - 不要犹豫,将其编辑回您之前的内容。你知道,我可能对.endEditing 感到困惑,它确实在下面的所有视图中递归。【参考方案11】:

详情

Xcode 10.2.1 (10E1001)、Swift 5

解决方案 1

endEditing(_:)

let gesture = UITapGestureRecognizer(target: tableView, action: #selector(UITextView.endEditing(_:)))
tableView.addGestureRecognizer(gesture)

溶液的使用1.全样

import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 30))
        textField.borderStyle = .roundedRect
        textField.placeholder = "Enter text"
        textField.becomeFirstResponder()
        view.addSubview(textField)
        let gesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:)))
        view.addGestureRecognizer(gesture)
    

解决方案 2

类 TapGestureRecognizer

import UIKit

class TapGestureRecognizer: UITapGestureRecognizer 

    let identifier: String

    init(target: Any?, action: Selector?, identifier: String) 
        self.identifier = identifier
        super.init(target: target, action: action)
    

    static func == (left: TapGestureRecognizer, right: TapGestureRecognizer) -> Bool 
        return left.identifier == right.identifier
    

扩展 UIView

import UIKit

extension UIView 

    private var hideKeybordOnTapIdentifier: String  return "hideKeybordOnTapIdentifier" 

    private var hideKeybordOnTapGestureRecognizer: TapGestureRecognizer? 
        let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(UIView.hideKeyboard),
                                                       identifier: hideKeybordOnTapIdentifier)
        if let gestureRecognizers = self.gestureRecognizers 
            for gestureRecognizer in gestureRecognizers 
                if let tapGestureRecognizer = gestureRecognizer as? TapGestureRecognizer,
                    tapGestureRecognizer == hideKeyboardGesture 
                    return tapGestureRecognizer
                
            
        
        return nil
    

    @objc private func hideKeyboard()  endEditing(true) 

    var hideKeyboardOnTap: Bool 
        set 
            let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(hideKeyboard),
                                                           identifier: hideKeybordOnTapIdentifier)
            if let hideKeybordOnTapGestureRecognizer = hideKeybordOnTapGestureRecognizer 
                removeGestureRecognizer(hideKeybordOnTapGestureRecognizer)
                if gestureRecognizers?.count == 0  gestureRecognizers = nil 
            
            if newValue  addGestureRecognizer(hideKeyboardGesture) 
        
        get  return hideKeybordOnTapGestureRecognizer == nil ? false : true 
    

解决方案2的使用

view.hideKeyboardOnTap = true

解决方案 2 完整示例

import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 30))
        textField.borderStyle = .roundedRect
        textField.placeholder = "Enter text"
        textField.becomeFirstResponder()
        view.addSubview(textField)
        view.hideKeyboardOnTap = true
    

【讨论】:

【参考方案12】:

看看这个。

override func viewDidLoad() 
    var tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
    self.view.userInteractionEnabled = true
    self.view.addGestureRecognizer(tapGesture)

那么你的点击处理程序就是。

  func handleTap(sender: UITapGestureRecognizer) 
    self.view.endEditing(true)

【讨论】:

imgView.addGestureRecognizer(tapGesture) 应该是self.view.addGestureRecognizer(tapGesture) 是的,对不起,我没有注意到。我在输入什么。谢谢@AhsanEbrahim【参考方案13】:

斯威夫特 3

override func viewDidLoad() 
    super.viewDidLoad()
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))

【讨论】:

【参考方案14】:
func findAndResignFirstResponder(_ stView: UIView) -> Bool 

    if stView.isFirstResponder 
        stView.resignFirstResponder()
        return true
    
    for subView: UIView in stView.subviews 
        if findAndResignFirstResponder(subView) 
            return true
        
    
    return false

【讨论】:

【参考方案15】:

对于 Swift 3

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

【讨论】:

【参考方案16】:

//在 swift 4..它对我有用。

func setupKeyboardDismissRecognizer()
    let tapRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(searchingActivity.dismissKeyboard))

    self.view.addGestureRecognizer(tapRecognizer)


    @objc func dismissKeyboard()
    
        view.endEditing(true)
        searchTableView.isHidden = true
    

//在viewDidLoad中调用这个函数setupKeyboardDismissRecognizer()

【讨论】:

【参考方案17】:

在 Swift4 中

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

【讨论】:

【参考方案18】:

在 Swift 4 或 5 中你可以使用 like..

class ViewController: UIViewController 

  override func viewDidLoad() 
    super.viewDidLoad()

    //Key borad dismiss
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
    tap.cancelsTouchesInView = false
    view.addGestureRecognizer(tap)
  

 //Key board hide on outside the textfield
 @objc func dismissKeyboard() 
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)
  

【讨论】:

【参考方案19】:

我在 Swift 4 中使用了以下代码,你可以试试这个,

override func viewDidLoad() 
    super.viewDidLoad()

    // dismiss keyboard when tap outside a text field 
    let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(YourViewControllerName.dismissKeyboard))
    view.addGestureRecognizer(tapGestureRecognizer)


//Calls this function when the tap is recognized.
func dismissKeyboard() 
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

【讨论】:

以上是关于触摸 UITextField 以外的任何地方时如何关闭键盘(快速)?的主要内容,如果未能解决你的问题,请参考以下文章

禁用除按钮内部以外的任何地方的触摸? - 斯威夫特

当用户按下其他控件/空格时,如何取消对UITextField的聚焦?

触摸整个应用程序时如何关闭键盘

触摸时 UITextField 崩溃

编辑 UITextView 并在表格视图控制器中触摸键盘以外的任何位置时无法关闭键盘

如何告诉带有 UITextField 的自定义 UIView 接收触摸事件