Reputation: 6537
I have been looking all over for this but I can't seem to find it. I know how to dismiss the keyboard using Objective-C
but I have no idea how to do that using Swift
? Does anyone know?
Upvotes: 510
Views: 519665
Reputation: 641
//Below function hides the keyboard when we click outside the textBox
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
super.touchesBegan(touches, with: event)
}
You can put this code in your ViewController and it will let you dismiss the keyboard by touching anywhere outside the textfield.
Upvotes: 1
Reputation: 2294
I am surprised, that none of the answers cover all edge cases. Possible edge cases in 2023:
Why UITapGesture
's action is bad for this? UITapGestureRecognizer only calls its action
if it triggers and it doesn't trigger if touch moves. So if you have a scrollview, or tableview, or interactive modal view and user tries to scroll/interact with them, the keyboard will fail to be dismissed. Furthermore, if you add gesture recognizer to your view controller, tapping navbar will fail to trigger the action as its outside of view's bounds. Lastly, there edge case where tap gesture doesn't work at all - swipe initiated from the cell that should not dismiss the keyboard (but the scroll should do it).
So we have established that we can't rely on UITapGestureRecognizer
action, but what can we use instead? The UIPanGesture
and its delegate.
To make the gesture recognizer transparent it needs to be defined with the following properties. This way it won't interfere with any other interactions. Put this code in your ViewController:
class MyViewController: UIViewController {
lazy var tapOutsideGestureRecognizer: UIPanGestureRecognizer = {
let control = UIPanGestureRecognizer(target: self, action: #selector(detectSwipe))
control.cancelsTouchesInView = false
control.delaysTouchesBegan = false
control.delaysTouchesEnded = false
control.delegate = self
return control
}()
// This will be used to handle one edge case
var viewOrigin: CGPoint?
...
}
Then we use the delegate to cancel any touches that begin outside the list of excluded view, but trigger our code instead. Put this anywhere, but its best to keep in your ViewController.swift file.
extension MyViewController: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
// We capture origin of the view, to detect swipe/scroll anywhere in the display tree
viewOrigin = view.convert(view.bounds.origin, to: nil)
return endEditingIfNeeded(touch: touch)
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
In the code that triggers when user taps anywhere, we want to exclude some views from dismissing the keyboard. Put this code in your ViewController:
extension MyViewController {
@objc func detectSwipe(sender: UIPanGestureRecognizer) {
guard sender.state == .changed, let viewOrigin else { return }
let newOrigin = view.convert(view.bounds.origin, to: nil)
if abs(newOrigin.y - viewOrigin.y) > 1 || abs(newOrigin.x - viewOrigin.x) > 1 {
tappedOutside()
}
}
@objc func endEditingIfNeeded(touch: UITouch) -> Bool {
// Array of views that shouldn't dismiss the keyboard
let exclude = [view.pickerContainerView, view.inputTextField]
for target in exclude {
// If tap origin is within excluded view, don't dismiss the keyboard
if target.bounds.contains(touch.location(in: target)) {
return true
}
}
// If tap originates in a view different than exclusion list, dismiss the keyboard or perform some other action
tappedOutside()
return false
}
func tappedOutside() {
// This line is optional and only should be used if you decide to add gesture recognizer to navigation controller (see explanation at the bottom of this answer)
// navigationController?.view.removeGestureRecognizer(tapOutsideGestureRecognizer)
}
There are two options to add this gesture recognizer:
view.addGestureRecognizer(tapOutsideGestureRecognizer)
. It will work anywhere in the view, but if the view is presented in navigation controller, tapping navbar wouldn't trigger the code.navigationController?.view.addGestureRecognizer(tapOutsideGestureRecognizer)
. If you go this route, you must remove gesture recognizer endEditingIfNeeded
to prevent it from outliving the view.
Last but not least. If you want to cover whole screen, not just the view area,Upvotes: 0
Reputation: 16072
To expand on Esqarrouth's answer, I always use the following to dismiss the keyboard, especially if the class from which I am dismissing the keyboard does not have a view
property and/or is not a subclass of UIView
.
UIApplication.shared.keyWindow?.endEditing(true)
Or, for convenience,
UIApplication.endEditing(true)
with the following extension to the UIApplication
class:
extension UIApplication {
/// Dismisses the keyboard from the key window of the
/// shared application instance.
///
/// - Parameters:
/// - force: specify `true` to force first responder to resign.
open class func endEditing(_ force: Bool = false) {
shared.endEditing(force)
}
/// Dismisses the keyboard from the key window of this
/// application instance.
///
/// - Parameters:
/// - force: specify `true` to force first responder to resign.
open func endEditing(_ force: Bool = false) {
keyWindow?.endEditing(force)
}
}
Upvotes: 14
Reputation: 349
how to dismiss keyboard when you click anywhere to close it
//Setup dismiss keyboard gesture
let tap = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
//Calling this function when the tapped
@objc func dismissKeyboard() {
view.endEditing(true)
}
Upvotes: 4
Reputation: 844
I haven't seen it mentioned, but NotificationCenter can tell you when the keyboard opens and closes. For example, this can be used if you want to change cancelsTouchesInView or remove the gesture recognizer all together.
Example:
var dismissKeyboardGestureRecognizer = UITapGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
//Setup dismiss keyboard gesture
self.dismissKeyboardGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
//Add Notifications
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name:UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidHide), name:UIResponder.keyboardDidHideNotification, object: nil)
}
@objc func keyboardDidShow() {
dismissKeyboardGestureRecognizer.cancelsTouchesInView = true
view.addGestureRecognizer(dismissKeyboardGestureRecognizer)
}
@objc func keyboardDidHide() {
dismissKeyboardGestureRecognizer.cancelsTouchesInView = false
view.removeGestureRecognizer(dismissKeyboardGestureRecognizer)
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
Upvotes: 1
Reputation: 81
If you want to dissmiss the keyboard, when you want go to the next button action or anyplace.
you can simply add the below line, Replace the textfield name of yours.
billTextField.endEditing(true) or billTextField.resignFirstResponder()
Upvotes: 0
Reputation: 411
Just one line of code in viewDidLoad()
method:
view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
Upvotes: 13
Reputation: 39201
override func viewDidLoad() {
super.viewDidLoad()
//Looks for single or multiple taps.
let tap = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
Here is another way to do this task if you are going to use this functionality in multiple UIViewControllers
:
// Put this piece of code anywhere you like
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
}
Now in every UIViewController
, all you have to do is call this function:
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
This function is included as a standard function in my repo which contains a lot of useful Swift Extensions like this one, check it out: https://github.com/goktugyil/EZSwiftExtensions
Upvotes: 1513
Reputation: 10532
Here is how to dismiss the keyboard by tapping anywhere else, in 2 lines using Swift 5.
(I hate to add another answer, but since this is the top result on Google I will to help rookies like me.)
In your ViewController.swift, find the viewDidLoad()
function.
Add these 2 lines:
let tap: UIGestureRecognizer = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing))
view.addGestureRecognizer(tap)
Upvotes: 3
Reputation: 153
In swift you can use
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
view.endEditing(true)
}
Upvotes: 13
Reputation: 105
A simple way to do this is by selecting the text field and using the method endEditing(true)
e.g
exampleTextField.endEditing(true)
Upvotes: 0
Reputation: 418
Able to achieve this by adding a global tap gesture recognizer to the window
property in the AppDelegate
.
This was a very catch all approach and might not be the desired solution for some but it worked for me. Please let me know if there any pitfalls to this solution.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Globally dismiss the keyboard when the "background" is tapped.
window?.addGestureRecognizer(
UITapGestureRecognizer(
target: window,
action: #selector(UIWindow.endEditing(_:))
)
)
return true
}
}
Upvotes: 1
Reputation: 31647
Create extension as below & call hideKeyboardWhenTappedAround()
in your Base view controller.
//
// UIViewController+Extension.swift
// Project Name
//
// Created by ABC on 2/3/18.
// Copyright © 2018 ABC. All rights reserved.
//
import UIKit
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tapGesture = UITapGestureRecognizer(target: self,
action: #selector(hideKeyboard))
view.addGestureRecognizer(tapGesture)
}
@objc func hideKeyboard() {
view.endEditing(true)
}
}
Most important thing to call in your Base View Controller so that no need to call all time in all view controllers.
Upvotes: 63
Reputation: 1760
Use IQKeyboardmanager that will help you solve easy.....
/////////////////////////////////////////
![ how to disable the keyboard..][1]
import UIKit
class ViewController: UIViewController,UITextFieldDelegate {
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
username.delegate = self
password.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(textField: UITextField!) -> Bool // called when 'return' key pressed. return NO to ignore.
{
textField.resignFirstResponder()
return true;
}
override func touchesBegan(_: Set<UITouch>, with: UIEvent?) {
username.resignFirstResponder()
password.resignFirstResponder()
self.view.endEditing(true)
}
}
Upvotes: 9
Reputation: 3085
Posting as a new answer since my edit of @King-Wizard's answer was rejected.
Make your class a delegate of the UITextField and override touchesBegan.
Swift 4
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
}
//Called when 'return' key is pressed. Return false to keep the keyboard visible.
func textFieldShouldReturn(textField: UITextField) -> Bool {
return true
}
// Called when the user clicks on the view (outside of UITextField).
override func touchesBegan(touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
Upvotes: 4
Reputation: 16189
swift 5 just two lines is enough. Add into your viewDidLoad
should work.
let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
view.addGestureRecognizer(tapGesture)
If your tap gesture blocked some other touches, then add this line:
tapGesture.cancelsTouchesInView = false
Upvotes: 34
Reputation: 1408
I have use IQKeyBoardManagerSwift for keyboard. it is easy to use. just Add pod 'IQKeyboardManagerSwift'
Import IQKeyboardManagerSwift and write code on didFinishLaunchingWithOptions
in AppDelegate
.
///add this line
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true
Upvotes: 11
Reputation: 2869
Add this extension to your ViewController :
extension UIViewController {
// Ends editing view when touches to view
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
self.view.endEditing(true)
}
}
Upvotes: 9
Reputation: 283
In Swift 4, add @objc:
In the viewDidLoad:
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
view.addGestureRecognizer(tap)
Function:
@objc func dismissKeyboard() {
view.endEditing(true)
}
Upvotes: 7
Reputation: 4466
override func viewDidLoad() {
super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))
}
func tap(sender: UITapGestureRecognizer){
print("tapped")
view.endEditing(true)
}
Try this,It's Working
Upvotes: 2
Reputation: 69
Swift 3
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
Upvotes: 1
Reputation: 516
For Swift3
Register an event recogniser in viewDidLoad
let tap = UITapGestureRecognizer(target: self, action: #selector(hideKeyBoard))
then we need to add the gesture into the view in same viewDidLoad.
self.view.addGestureRecognizer(tap)
Then we need to initialise the registered method
func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
view.endEditing(true)
}
Upvotes: 3
Reputation: 59
Here's a succinct way of doing it:
let endEditingTapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:)))
endEditingTapGesture.cancelsTouchesInView = false
view.addGestureRecognizer(endEditingTapGesture)
Upvotes: 2
Reputation: 547
I found this simple solution: 1. Add UITapGestureRecognizer to your view Controller 2. Add IBAction to your UITapGestureRecognizer 3. Finally you can resign the first responder
class ViewController: UIViewController
{
@IBOutlet var tap: UITapGestureRecognizer!
@IBOutlet weak var label: UILabel!
@IBOutlet weak var textField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func dismissUsingGesture(_ sender: UITapGestureRecognizer)
{
self.textField.resignFirstResponder()
label.text = textField.text!
}
}
Upvotes: 1
Reputation: 1934
If you use a scroll view, It could be much simpler.
Just select Dismiss interactively
in storyboard.
Upvotes: 8
Reputation: 71
As a novice programmer it can be confusing when people produce more skilled and unnecessary responses...You do not have to do any of the complicated stuff shown above!...
Here is the simplest option...In the case your keyboard appears in response to the textfield - Inside your touch screen function just add the resignFirstResponder function. As shown below - the keyboard will close because the First Responder is released (exiting the Responder chain)...
override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
MyTextField.resignFirstResponder()
}
Upvotes: 6
Reputation: 405
for Swift 3 it is very simple
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
if you want to hide keyboard on pressing RETURN key
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
but in second case you will also need to pass delegate from all textFields to the ViewController in the Main.Storyboard
Upvotes: 24
Reputation: 624
Swift 3: Easiest way to dismiss keyboard:
//Dismiss keyboard method
func keyboardDismiss() {
textField.resignFirstResponder()
}
//ADD Gesture Recignizer to Dismiss keyboard then view tapped
@IBAction func viewTapped(_ sender: AnyObject) {
keyboardDismiss()
}
//Dismiss keyboard using Return Key (Done) Button
//Do not forgot to add protocol UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
keyboardDismiss()
return true
}
Upvotes: 13
Reputation: 17152
Swift 3:
Extension with Selector
as parameter to be able to do additional stuff in the dismiss function and cancelsTouchesInView
to prevent distortion with touches on other elements of the view.
extension UIViewController {
func hideKeyboardOnTap(_ selector: Selector) {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: selector)
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
}
Usage:
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardOnTap(#selector(self.dismissKeyboard))
}
func dismissKeyboard() {
view.endEditing(true)
// do aditional stuff
}
Upvotes: 10
Reputation: 2132
If you have other views that should receive the touch as well you have to set
cancelsTouchesInView = false
Like this:
let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
elsewhereTap.cancelsTouchesInView = false
self.view.addGestureRecognizer(elsewhereTap)
Upvotes: 2