I'm trying to make the text field txtAdd swipe up when the keyboard shows up, but I'm not really sure how to do it.
This is the code for adding items to the list:
#IBAction func submitBntFunc(_ sender: Any) {
if let text = txtAdd.text{
if text == ""{
return
}
txtAdd.text = ""
txtAdd.resignFirstResponder()
return txtField.text.append("\(text) \n")
}
}
I tried with the code below but it didn't really work.
guard let keyboardSize = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else {return}
try with this code
var originButton : CGFloat?
override func viewDidLoad()
{
originButton = self.YOURBUTTON.frame.origin.y
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboard = ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) {
if self.view.frame.origin.y == 0 {
self.YOURBUTTON.frame.origin.y -= keyboard.height
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if self.YOURBUTTON.frame.origin.y != originButton {
self.YOURBUTTON.frame.origin.y = originButton!
}
}
add this Observer in your viewDidLoad methods:=
NotificationCenter.default.addObserver(self, selector: #selector(keyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
And it is call this function:=
#objc func keyboard(notification: Notification){
let userInfo = notification.userInfo!
let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, to: view.window)
if notification.name == UIResponder.keyboardWillHideNotification{
//add your constrain here when keyboard is hiden
self.scrollView.contentInset = UIEdgeInsets.zero
}else{
//add your constrain here when keyboard is visible
self.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)
}
scrollView.scrollIndicatorInsets = scrollView.contentInset
}
How do you adjust your scrollview to compensate for a keyboard vertically? Read on...
Yes I know this is some basic info, but I randomly noticed today that all of the answers I saw about this topic are all over the place with info, versions and/or use bangs all over the place... but nothing solid for Swift 3+.
Swift 4.2:
Substitute scrollView for UITableView, UICollectionView, etc.
let scrollView = UIScrollView()
Add observers.
override open func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
}
Add some functions to listen for the notifications:
#objc func keyboardWillHide(notification: Notification) {
let contentInsets = UIEdgeInsets.zero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
#objc func keyboardWillShow(notification: Notification) {
guard let keyboardFrame: CGRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
scrollView.contentInset.bottom = keyboardFrame.height
}
Worth noting is that if your deployment target is iOS 9 or greater, you don't need to remove the observer anymore. Check the NotificationCenter docs for more info.
deinit {
NotificationCenter.default.removeObserver(self)
}
------------------------------------------------
Swift 3:
let scrollView = UIScrollView()
Add observers.
override open func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(noti:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
NSNotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(noti:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
Add some functions to listen for the notifications:
func keyboardWillHide(noti: Notification) {
let contentInsets = UIEdgeInsets.zero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
func keyboardWillShow(noti: Notification) {
guard let userInfo = noti.userInfo else { return }
guard var keyboardFrame: CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return }
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = scrollView.contentInset
contentInset.bottom = keyboardFrame.size.height
scrollView.contentInset = contentInset
}
Worth noting is that if your deployment target is iOS 9 or greater, you don't need to remove the observer anymore. Check the NotificationCenter docs for more info.
deinit {
NotificationCenter.default.removeObserver(self)
}
A modification to make it work on iOS 11 is to use UIKeyboardFrameEndUserInfoKey rather than UIKeyboardFrameBeginUserInfoKey. Just a simplified approach to #crewshin's solution:
#objc func keyboardWillShow(_ notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
scrollView.contentInset.bottom = keyboardSize.height
}
}
#objc func keyboardWillHide(_ notification: NSNotification) {
scrollView.contentInset.bottom = 0
}
I tryed to use something to move up the view because when I go at the end of my form and I tap on the last textfield I can't see what I write in because the keyboard appears over the text field, so I found something but here if I tap on a textfield on the top of the view this one gonna gonna be hide by going upper, that's the code:
override func viewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y -= keyboardSize.height
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y += keyboardSize.height
}
}
But here there is an another problem, when I tap two times one an another textfield, a black bloc appears.
So what I wan't to do is detect the textfield and put the keyboard under it so move up the textfield. And detect if the keyboard is already here do don't show a black bloc. But I haven't found solution about.
I have used this code in my project :
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
// Register Keyboard Notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
// Remove Keyboard notification observer
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillShow(notification: NSNotification)
{
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil)
var contentInset:UIEdgeInsets = self.scrollView.contentInset
contentInset.bottom = keyboardFrame.size.height - 30 //Set this value (30) according to your code as i have navigation tool bar for next and prev.
self.scrollView.contentInset = contentInset
}
func keyboardWillHide(notification: NSNotification) {
let contentInset:UIEdgeInsets = UIEdgeInsetsZero
self.scrollView.contentInset = contentInset
}
Hope It will help you!!
Add a bool property self.isKeyBoardUp
In keyboardWillShow:
If isKeyBoardUp return, else set it to true and do your stuff.
In keyboardWillHide:
If not isKeyBoardUp return, else set it to false and do your stuff.
Please check this code i am try it and works for get this one from
Move textfield when keyboard appears swift
func keyboardWasShown(notification: NSNotification) {
var info = notification.userInfo!
var keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.bottomConstraint.constant = keyboardFrame.size.height + 20
})
}
I have set the notifications to keep the text in textView above the keyboard. My problem is, when I select the table view cell to display my text in the next VC, that the text appears few lines below the top and only after I start editing (keyboard shows up) and than swipe to dismiss the keyboard, text repositions itself at the top, where it should be.How can I force the text to be at the top as soon as VC displays its content, before the keyboard appears? Thanks.
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: "adjustForKeyboard:", name: UIKeyboardWillHideNotification, object: nil)
notificationCenter.addObserver(self, selector: "adjustForKeyboard:", name: UIKeyboardWillChangeFrameNotification, object: nil)
storyTextView.text = passedText
title = passedTitle
navigationController?.navigationBar.tintColor = UIColor.redColor()
}
func adjustForKeyboard(notification: NSNotification) {
let userInfo = notification.userInfo!
let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let keyboardViewEndFrame = view.convertRect(keyboardScreenEndFrame, fromView: view.window)
if notification.name == UIKeyboardWillHideNotification {
storyTextView.contentInset = UIEdgeInsetsZero
}else {
storyTextView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)
}
storyTextView.scrollIndicatorInsets = storyTextView.contentInset
let selectedRange = storyTextView.selectedRange
storyTextView.scrollRangeToVisible(selectedRange)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
storyTextView.contentInset = UIEdgeInsetsZero
}
The height of a keyboard on varying iOS devices is different. Does anybody know how I can get height of a device's keyboard programmatically?
Swift
You can get the keyboard height by subscribing to the UIKeyboardWillShowNotification notification. (Assuming you want to know what the height will be before it's shown).
Swift 4
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow),
name: UIResponder.keyboardWillShowNotification,
object: nil
)
#objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
}
}
Swift 3
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil
)
#objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
}
}
Swift 2
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
func keyboardWillShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo!
let keyboardFrame: NSValue = userInfo.valueForKey(UIKeyboardFrameEndUserInfoKey) as! NSValue
let keyboardRectangle = keyboardFrame.CGRectValue()
let keyboardHeight = keyboardRectangle.height
}
Swift 3.0 and Swift 4.1
1- Register the notification in the viewWillAppear method:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
2- Method to be called:
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardSize.height
print(keyboardHeight)
}
}
Swift 4 and Constraints
To your tableview add a bottom constraint relative to the bottom safe area. In my case the constraint is called tableViewBottomLayoutConstraint.
#IBOutlet weak var tableViewBottomLayoutConstraint: NSLayoutConstraint!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(notification:)), name: .UIKeyboardWillHide, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow , object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide , object: nil)
}
#objc
func keyboardWillAppear(notification: NSNotification?) {
guard let keyboardFrame = notification?.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
return
}
let keyboardHeight: CGFloat
if #available(iOS 11.0, *) {
keyboardHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
} else {
keyboardHeight = keyboardFrame.cgRectValue.height
}
tableViewBottomLayoutConstraint.constant = keyboardHeight
}
#objc
func keyboardWillDisappear(notification: NSNotification?) {
tableViewBottomLayoutConstraint.constant = 0.0
}
Update Swift 4.2
private func setUpObserver() {
NotificationCenter.default.addObserver(self, selector: .keyboardWillShow, name: UIResponder.keyboardWillShowNotification, object: nil)
}
selector method:
#objc fileprivate func keyboardWillShow(notification:NSNotification) {
if let keyboardRectValue = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardRectValue.height
}
}
extension:
private extension Selector {
static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(notification:))
}
Update Swift 3.0
private func setUpObserver() {
NotificationCenter.default.addObserver(self, selector: .keyboardWillShow, name: .UIKeyboardWillShow, object: nil)
}
selector method:
#objc fileprivate func keyboardWillShow(notification:NSNotification) {
if let keyboardRectValue = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardRectValue.height
}
}
extension:
private extension Selector {
static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(notification:))
}
Tip
UIKeyboardDidShowNotification or UIKeyboardWillShowNotification might called twice and got different result, this article explained why called twice.
In Swift 2.2
Swift 2.2 deprecates using strings for selectors and instead introduces new syntax: #selector.
Something like:
private func setUpObserver() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: .keyboardWillShow, name: UIKeyboardWillShowNotification, object: nil)
}
selector method:
#objc private func keyboardWillShow(notification:NSNotification) {
let userInfo:NSDictionary = notification.userInfo!
let keyboardFrame:NSValue = userInfo.valueForKey(UIKeyboardFrameEndUserInfoKey) as! NSValue
let keyboardRectangle = keyboardFrame.CGRectValue()
let keyboardHeight = keyboardRectangle.height
editorBottomCT.constant = keyboardHeight
}
extension:
private extension Selector {
static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(_:))
}
Swift 5
override func viewDidLoad() {
// Registering for keyboard notification.
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
}
/* UIKeyboardWillShowNotification. */
#objc internal func keyboardWillShow(_ notification : Notification?) -> Void {
var _kbSize:CGSize!
if let info = notification?.userInfo {
let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
// Getting UIKeyboardSize.
if let kbFrame = info[frameEndUserInfoKey] as? CGRect {
let screenSize = UIScreen.main.bounds
//Calculating actual keyboard displayed size, keyboard frame may be different when hardware keyboard is attached (Bug ID: #469) (Bug ID: #381)
let intersectRect = kbFrame.intersection(screenSize)
if intersectRect.isNull {
_kbSize = CGSize(width: screenSize.size.width, height: 0)
} else {
_kbSize = intersectRect.size
}
print("Your Keyboard Size \(_kbSize)")
}
}
}
Shorter version here:
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight = keyboardSize.height
}
}
Swift 4 .
Simplest Method
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight : Int = Int(keyboardSize.height)
print("keyboardHeight",keyboardHeight)
}
}
Objective-C version:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
and then:
- (void)keyboardWillShow:(NSNotification *)notification
{
CGFloat height = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}
// Step 1 :- Register NotificationCenter
ViewDidLoad() {
self.yourtextfield.becomefirstresponder()
// Register your Notification, To know When Key Board Appears.
NotificationCenter.default.addObserver(self, selector: #selector(SelectVendorViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
// Register your Notification, To know When Key Board Hides.
NotificationCenter.default.addObserver(self, selector: #selector(SelectVendorViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
// Step 2 :-
These Methods will be called Automatically when Keyboard appears Or Hides
func keyboardWillShow(notification:NSNotification) {
let userInfo:NSDictionary = notification.userInfo! as NSDictionary
let keyboardFrame:NSValue = userInfo.value(forKey: UIKeyboardFrameEndUserInfoKey) as! NSValue
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
tblViewListData.frame.size.height = fltTblHeight-keyboardHeight
}
func keyboardWillHide(notification:NSNotification) {
tblViewListData.frame.size.height = fltTblHeight
}
The method by ZAFAR007 updated for Swift 5 in Xcode 10
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
}
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight : Int = Int(keyboardSize.height)
print("keyboardHeight",keyboardHeight)
}
}
I uses below code,
override func viewDidLoad() {
super.viewDidLoad()
self.registerObservers()
}
func registerObservers(){
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
#objc func keyboardWillAppear(notification: Notification){
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
self.view.transform = CGAffineTransform(translationX: 0, y: -keyboardHeight)
}
}
#objc func keyboardWillHide(notification: Notification){
self.view.transform = .identity
}
I had to do this. this is a bit of hackery. not suggested.
but i found this very helpful
I made extension and struct
ViewController Extension + Struct
import UIKit
struct viewGlobal{
static var bottomConstraint : NSLayoutConstraint = NSLayoutConstraint()
}
extension UIViewController{ //keyboardHandler
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
func listenerKeyboard(bottomConstraint: NSLayoutConstraint) {
viewGlobal.bottomConstraint = bottomConstraint
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
// Register your Notification, To know When Key Board Hides.
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
//Dismiss Keyboard
#objc func dismissKeyboard() {
view.endEditing(true)
}
#objc func keyboardWillShow(notification:NSNotification) {
let userInfo:NSDictionary = notification.userInfo! as NSDictionary
let keyboardFrame:NSValue = userInfo.value(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
UIView.animate(withDuration: 0.5){
viewGlobal.bottomConstraint.constant = keyboardHeight
}
}
#objc func keyboardWillHide(notification:NSNotification) {
UIView.animate(withDuration: 0.5){
viewGlobal.bottomConstraint.constant = 0
}
}
}
Usage:
get most bottom constraint
#IBOutlet weak var bottomConstraint: NSLayoutConstraint! // default 0
call the function inside viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
listenerKeyboard(bottomConstraint: bottomConstraint)
// Do any additional setup after loading the view.
}
Hope this help. -you keyboard will now auto close when user tap outside of textfield and -it will push all view to above keyboard when keyboard appear.-you could also used dismissKeyboard() when ever you need it
if let keyboardSize = (sender.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
{
let keyboardHeight = keyboardSize.height
print(keyboardHeight)
}