如何在触摸 UITextField 之外的任何地方时关闭键盘(swift)?

How to dismiss keyboard when touching anywhere outside UITextField (in swift)?

我正在处理一个有 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)
}

当我点击滚动视图外部时,它对我有用,但是当我点击滚动视图时,没有任何反应,键盘也没有隐藏。

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

在这种情况下,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()
    }
}

我在 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 你在做什么,它都会隐藏键盘。

转到键盘类型和Select默认值或您需要文本字段的任何内容。然后重写一个方法,随心所欲地调用它,我通常称它为 touchingBegins。以下是您忘记添加的内容

super.touchingBegins(touches, withEvent: event)
 }

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

对于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)
}

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

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

它应该有效

希望对您有所帮助!

已编辑 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()

每次触摸不同的 文本字段 关闭键盘或使用 resignfirstresponder

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
 UITouch *touch = [touches anyObject];
 if(![touch.view isMemberOfClass:[UITextField class]]) {
     [touch.view endEditing:YES];
 }
}

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

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

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

使用代码:

你的文本字段名称.resignfirsterresponder()

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

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. 当前选择的答案应该是下面的答案。

详情

  • 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

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

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

看看这个。

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

swift 3

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
}
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
}

对于Swift 3

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

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

在 Swift4 中

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

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

我在Swift4中使用了下面的代码,你可以试试这个,

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