Move view with keyboard using Swift

IosSwiftUikitNsnotificationcenterUikeyboard

Ios Problem Overview


I have an app that has a text field on the lower half of the view. This means that when I go to type in the text field the keyboard covers the textfield.

How would I go about moving the view upwards while typing so I can see what i'm typing and then moving it back down to its original place when the keyboard disappears?

I've looked everywhere but all the solutions appear to be in Obj-C which I can't quite convert just yet.

Any help would be greatly appreciated.

Ios Solutions


Solution 1 - Ios

Here is a solution, without handling the switch from one textField to another:

override func viewDidLoad() {
    	super.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?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
		self.view.frame.origin.y -= keyboardSize.height
	}            
}

func keyboardWillHide(notification: NSNotification) {
	self.view.frame.origin.y = 0
}

To solve this, replace the two functions keyboardWillShow/Hide with these:

func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

func keyboardWillHide(notification: NSNotification) {
    if view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}
Swift 3.0:
override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}
    
Swift 4.0:
override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}
Swift 4.2:
override func viewDidLoad() {
    super.viewDidLoad()            
    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 keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
		if self.view.frame.origin.y == 0 {
			self.view.frame.origin.y -= keyboardSize.height
		}
	}
}

@objc func keyboardWillHide(notification: NSNotification) {
	if self.view.frame.origin.y != 0 {
		self.view.frame.origin.y = 0
	}
}

Solution 2 - Ios

Easiest way that doesn't even require any code:

  1. Download https://github.com/MengTo/Spring/blob/master/Spring/KeyboardLayoutConstraint.swift" title="KeyboardLayoutConstraint.swift">KeyboardLayoutConstraint.swift and add (drag & drop) the file into your project, if you're not using the Spring animation framework already.
  2. In your storyboard, create a bottom constraint for the View or Textfield, select the constraint (double-click it) and in the Identity Inspector, change its class from NSLayoutConstraint to KeyboardLayoutConstraint.
  3. Done!

The object will auto-move up with the keyboard, in sync.

Solution 3 - Ios

One of the popular answers on this thread uses the following code:

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

There's an obvious problem with offsetting your view by a static amount. It'll look nice on one device but will look bad on any other size configuration. You'll need to get the keyboards height and use that as your offset value.

Here's a solution that works on all devices and handles the edge-case where the user hides the predictive text field while typing.

Solution

Important to note below, we're passing self.view.window in as our object parameter. This will provide us with data from our Keyboard, such as its height!

@IBOutlet weak var messageField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)
}

func keyboardWillHide(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    self.view.frame.origin.y += keyboardSize.height
}

We'll make it look nice on all devices and handle the case where the user adds or removes the predictive text field.

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y -= keyboardSize.height
        })
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y += keyboardSize.height - offset.height
        })
    }
}

Remove Observers

Don't forget to remove your observers before you leave the view to prevent unnecessary messages from being transmitted.

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}

Update based on question from comments:

If you have two or more text-fields, you can check to see if your view.frame.origin.y is at zero.

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
       
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size
        
    if keyboardSize.height == offset.height {
        if self.view.frame.origin.y == 0 {
            UIView.animateWithDuration(0.1, animations: { () -> Void in
                self.view.frame.origin.y -= keyboardSize.height
            })
        }
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y += keyboardSize.height - offset.height
        })
    }
     print(self.view.frame.origin.y)
}

Solution 4 - Ios

Not an advertisement or promotion or spam, just a good solution. I know that this question has nearly 30 answers and I'm so shocked that no one even mentioned once about this beautiful GitHub project that does it all for you and even better. All the answers just move the view upwards. I just solved all my problems with this IQKeyboardManager. It has 13000+ stars.
Just add this in your podfile if you are using swift

pod 'IQKeyboardManagerSwift'

and then inside your AppDelegate.swift do import IQKeyboardManagerSwift

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

      IQKeyboardManager.shared.enable = true // just add this line

      return true
    }
}

Add the line IQKeyboardManager.shared.enable = true to enable it
This solution is a must if you are going for production.

Solution 5 - Ios

I improved one of the answers a bit to make it work with different keyboards & different textviews/fields on one page:

Add observers:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

func keyboardWillHide() {
    self.view.frame.origin.y = 0
}

func keyboardWillChange(notification: NSNotification) {
    
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if YOURTEXTVIEW.isFirstResponder {
            self.view.frame.origin.y = -keyboardSize.height
        }
    }
}

Remove observers:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

Solution 6 - Ios

Add this to your viewcontroller. Works like a charm. Just adjust the values.

override func viewDidLoad() {
    super.viewDidLoad()        
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
}

@objc func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
@objc func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

Solution 7 - Ios

> Swift 5.0:

After 4-5 hours of fight i came with a simple extension of UIViewController with simple code which works like charm

*View should not move when TextField is above the keyboard

*No need to set constant value to NSLayoutConstraint

*No third party library required

*No animation code required

*Works on tableview as well

*This works on Auto layout / auto resize

extension UIViewController {
    func addKeyboardObserver() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotifications(notification:)),
                                               name: UIResponder.keyboardWillChangeFrameNotification,
                                               object: nil)
    }
    
    func removeKeyboardObserver(){
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }
    
    // This method will notify when keyboard appears/ dissapears
    @objc func keyboardNotifications(notification: NSNotification) {
        
        var txtFieldY : CGFloat = 0.0  //Using this we will calculate the selected textFields Y Position
        let spaceBetweenTxtFieldAndKeyboard : CGFloat = 5.0 //Specify the space between textfield and keyboard
       
        
        var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        if let activeTextField = UIResponder.currentFirst() as? UITextField ?? UIResponder.currentFirst() as? UITextView {
            // Here we will get accurate frame of textField which is selected if there are multiple textfields
            frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
            txtFieldY = frame.origin.y + frame.size.height
        }
        
        if let userInfo = notification.userInfo {
            // here we will get frame of keyBoard (i.e. x, y, width, height)
            let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
            let keyBoardFrameY = keyBoardFrame!.origin.y
            let keyBoardFrameHeight = keyBoardFrame!.size.height
            
            var viewOriginY: CGFloat = 0.0
            //Check keyboards Y position and according to that move view up and down
            if keyBoardFrameY >= UIScreen.main.bounds.size.height {
                viewOriginY = 0.0
            } else {
                // if textfields y is greater than keyboards y then only move View to up
                if txtFieldY >= keyBoardFrameY {
                    
                    viewOriginY = (txtFieldY - keyBoardFrameY) + spaceBetweenTxtFieldAndKeyboard
                    
                    //This condition is just to check viewOriginY should not be greator than keyboard height
                    // if its more than keyboard height then there will be black space on the top of keyboard.
                    if viewOriginY > keyBoardFrameHeight { viewOriginY = keyBoardFrameHeight }
                }
            }
            
            //set the Y position of view
            self.view.frame.origin.y = -viewOriginY
        }
    }
}

Add this Extension Of UIResponder to get which TextField is selected

extension UIResponder {
    
    static weak var responder: UIResponder?
    
    static func currentFirst() -> UIResponder? {
        responder = nil
        UIApplication.shared.sendAction(#selector(trap), to: nil, from: nil, for: nil)
        return responder
    }
    
    @objc private func trap() {
        UIResponder.responder = self
    }
}

Then use of this in your any ViewController

   override func viewWillAppear(_ animated: Bool) {
        self.addKeyboardObserver()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        self.removeKeyboardObserver()
    }

  • Register this Notification in func viewWillAppear(_ animated: Bool)

  • Deregister this Notification in func viewWillDisappear(_ animated:Bool)

Download Demo Here

Solution 8 - Ios

I see all answers are moving the view itself by the value of the keyboard height. Well, I have an elaborate answer, which could be useful if you are using constraints i.e autolayout, that moves a view by changing its constraint value (bottom or top constraints for example) by a predefined value or you can use keyboard size value.

In this example, I use bottom constraint from the textfield to Bottom Layout View with initial value of 175.

@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

override func viewDidLoad() {
    super.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) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 260
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

func keyboardWillHide(notification: NSNotification) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 175
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

Solution 9 - Ios

For Black Screen Error ( Swift 4 & 4.2 ) .

I fixed the black screen problem. In the verified solution The keyboard height changes after tapping and this is causing black screen.

Have to use UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey

var isKeyboardAppear = false

override func viewDidLoad() {
    super.viewDidLoad() 
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if !isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y == 0{
                self.view.frame.origin.y -= keyboardSize.height
            }
        }
        isKeyboardAppear = true
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y != 0{
                self.view.frame.origin.y += keyboardSize.height
            }
        }
         isKeyboardAppear = false
    }
}

Solution 10 - Ios

There have been som changes to how we define the KeyboardWillHideNotification.

This solution works with Swift 4.2:

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)


@objc func keyboardWillShow(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.origin.y -= keyboardSize.height
    }
}

@objc func keyboardWillHide(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.origin.y += keyboardSize.height
    }
}

Solution 11 - Ios

So none of the other answers seems to get it right.

The Good Behaviored Keyboard on iOS should:

  • Resize automatically when the keyboard change sizes (YES IT CAN)
  • Animate at the same speed as the keyboard
  • Animate using the same curve as the keyboard
  • Respect safe areas if relevant.
  • Works on iPad/Undocked mode too

My code use a NSLayoutConstraint declared as an @IBOutlet

@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!

You could also use transforms, view offsets, .... I think it's easier with the constraint tho. It works by setting a constraint to the bottom, you might need to alter the code if your constant is not 0/Not to the bottom.

Here is the code:

// In ViewDidLoad
    NotificationCenter.default.addObserver(self, selector: #selector(?MyViewController.keyboardDidChange), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)


@objc func keyboardDidChange(notification: Notification) {
    let userInfo = notification.userInfo! as [AnyHashable: Any]
    let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
    let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber
    bottomLayoutConstraint.constant = view.frame.height - endFrame.origin.y - view.safeAreaInsets.bottom // If your constraint is not defined as a safeArea constraint you might want to skip the last part.
    // Prevents iPad undocked keyboard.
    guard endFrame.height != 0, view.frame.height == endFrame.height + endFrame.origin.y else {
        bottomLayoutConstraint.constant = 0
        return
    }
    UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
    UIView.animate(withDuration: animationDuration.doubleValue) {
        self.view.layoutIfNeeded()
        // Do additional tasks such as scrolling in a UICollectionView
    }
}

Solution 12 - Ios

For Swift 3, I made a UIViewController subclass since I needed constant behavior in all View Controllers.

class SomeClassVC: UIViewController {
  
  //MARK: - Lifecycle
  override func viewDidLoad() {
    super.viewDidLoad()
    
    addKeyboardObservers()
  }
  
  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    
    removeKeyboardObservers()
  }
  
  //MARK: - Overrides
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
  }
  
  //MARK: - Help
  func addKeyboardObservers() {
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }
  
  func removeKeyboardObservers() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
  }

  func keyboardWillShow(notification: NSNotification) {
    let keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.origin.y = -1 * keyboardHeight!
      self.view.layoutIfNeeded()
    })
  }
  
  func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.origin.y = 0
      self.view.layoutIfNeeded()
    })
  }

  func resignTextFieldFirstResponders() {
    for textField in self.view.subviews where textField is UITextField {
      textField.resignFirstResponder()
    }
  }

  func resignAllFirstResponders() {
      view.endEditing(true)
  }
}

Solution 13 - Ios

The validated answer doesn't take in account the textfield position and has some bug (double displacement, never come back the primary position, displacement even if the texfield is on top of the view...)

The idea is :

  • to get the focus TextField absolute Y position
  • to get the keyboard height
  • to get the ScreenHeight
  • Then calculate the distance between keyboard position and textfield (if < 0 -> move up the view)
  • to use UIView.transform instead of UIView.frame.origin.y -= .., cause it's easier to come back to original position with UIView.transform = .identity

then we will be able to move the view only if necessary and of the specific displacement in oder to have the focused texField just over the keyboard

Here is the code :

Swift 4

class ViewController: UIViewController, UITextFieldDelegate {

var textFieldRealYPosition: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()
  
    NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  
  // Delegate all textfields

}


@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        let distanceBetweenTextfielAndKeyboard = self.view.frame.height - textFieldRealYPosition - keyboardSize.height
        if distanceBetweenTextfielAndKeyboard < 0 {
            UIView.animate(withDuration: 0.4) {
                self.view.transform = CGAffineTransform(translationX: 0.0, y: distanceBetweenTextfielAndKeyboard)
            }
        }
    }
}


@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.4) {
        self.view.transform = .identity
    }
}


func textFieldDidBeginEditing(_ textField: UITextField) {
  textFieldRealYPosition = textField.frame.origin.y + textField.frame.height
  //take in account all superviews from textfield and potential contentOffset if you are using tableview to calculate the real position
}

}

Solution 14 - Ios

I noticed that the other answers involved cutting some of the top from the view. If you want to simply resize the view without cutting any content, just try this method :)

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.setTranslatesAutoresizingMaskIntoConstraints(true)
        self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height - keyboardSize.height)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height + keyboardSize.height)
    }
}

Solution 15 - Ios

My two cents for beginners: in above samples someone changes coordinates, other uses "autoresizing mask", and other constraints:

As Apple says, do not mix these 3 types of logic. If You have constraints in Storyboard, do not try to change x/y. It definitively not work.

Solution 16 - Ios

Similar to @Boris answer, but in Swift 5:

override func viewDidLoad() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@IBAction func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

@IBAction func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

Solution 17 - Ios

For Swift 3

func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder
    
    //move textfields up
    let myScreenRect: CGRect = UIScreen.main.bounds
    let keyboardHeight : CGFloat = 216
    
    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var needToMove: CGFloat = 0
    
    var frame : CGRect = self.view.frame
    if (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
        needToMove = (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
    }
    
    frame.origin.y = -needToMove
    self.view.frame = frame
    UIView.commitAnimations()
}

func textFieldDidEndEditing(_ textField: UITextField) {
    //move textfields back down
    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var frame : CGRect = self.view.frame
    frame.origin.y = 0
    self.view.frame = frame
    UIView.commitAnimations()
}

Solution 18 - Ios

its 100% Perfect Answer For all Guy's Update Tableview Height when open Keyboard

For Swift4.2

   override func viewDidLoad() {
      super.viewDidLoad()
      NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
    
      NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
   }

   @objc func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {

        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)
        
        var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset
    }
}

   @objc func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        self.tbl.contentInset = contentInset
    }
}

Swift3.2

    override func viewDidLoad() {
          super.viewDidLoad()
  
           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    
           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    func keyboardWillShow(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         //self.view.frame.origin.y -= keyboardSize.height
         var userInfo = notification.userInfo!
         var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
          keyboardFrame = self.view.convert(keyboardFrame, from: nil)

          var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset

       }
    }

    func keyboardWillHide(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
         self.tbl.contentInset = contentInset
         }
    }

Solution 19 - Ios

Swift 4:

I was having an issue with the most accepted answer, in which hiding the keyboard did not return the view all the way to the bottom of the page (only partially). This worked for me (+updated for Swift 4).

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0{
            self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y != 0{
            self.view.frame.origin.y = 0
        }
    }
}

Solution 20 - Ios

Updated for Swift 3...

As others have said, you need to add notification observers in your controller's viewDidLoad() method, like so:

NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil)
    { notification in
    self.keyboardWillShow(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil)
    { notification in
    self.keyboardWillHide(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

Remember to remove your observers where appropriate (I do it in the viewWillDisappear() method)

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: nil)

Then, implement your show and hide methods - notice the line that tells the app to ignore interaction events (beginIgnoringInteractionEvents). This is important since without it, the user could tap on a field or even a scrollview and cause the shift to occur a second time, resulting in a terrible UI glitch. Ignoring interaction events prior to the keyboard showing and hiding will prevent this:

func keyboardWillShow(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.origin.y -= keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top += keyboardSize.height
        }
    }

func keyboardWillHide(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.origin.y += keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top -= keyboardSize.height
        }
    }

Lastly, re-enable user interactions (remember, this method fires after the keyboard didShow or didHide):

func enableUserInteraction()
    {
    UIApplication.shared.endIgnoringInteractionEvents()
    }

Solution 21 - Ios

Here is my solution (actually this code is for the case when you have few textfields in your view, this works also for the case when you have one textfield)

class MyViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!

var activeTextField: UITextField!
var viewWasMoved: Bool = false


override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}

override func viewDidDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func textFieldDidBeginEditing(textField: UITextField) {
    self.activeTextField = textField
}

func textFieldDidEndEditing(textField: UITextField) {
    self.activeTextField = nil
}

func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}


func keyboardWillShow(notification: NSNotification) {
    
    let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    
    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    
    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
    
    if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
        self.viewWasMoved = true
        self.view.frame.origin.y -= keyboardSize!.height
    } else {
        self.viewWasMoved = false
    }
}

func keyboardWillHide(notification: NSNotification) {
    if (self.viewWasMoved) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

Solution 22 - Ios

If you have 2 or more text fields on the same VC, and the user taps on one of them and then taps on the other one, without calling the function keyboardWillHide, the view is going upwards one more time, which is not necessary, because you'll have the keyboard, a blank space which has the height of the keyboard, and then the view, using the code in the answer I edited:

override func viewDidLoad() {       
    super.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
    }
}

To solve this, replace the two functions "KeyboardWillShow/Hide" to these:

func keyboardWillShow(notification: NSNotification) {
 if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
    if view.frame.origin.y == 0{
        self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.origin.y != 0 {
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

Solution 23 - Ios

Swift 3 code

var activeField: UITextField?

override func viewDidLoad() {
    super.viewDidLoad()
    
    NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if (self.activeField?.frame.origin.y)! >= keyboardSize.height {
            self.view.frame.origin.y = keyboardSize.height - (self.activeField?.frame.origin.y)!
        } else {
            self.view.frame.origin.y = 0
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    self.view.frame.origin.y = 0
}

Solution 24 - Ios

@Boris's solution is VERY good but the view can sometimes be corrupted.

For the perfect alignment, use the below code

override func viewDidLoad() {
super.viewDidLoad()            
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)}

Functions:

@objc func keyboardWillShow(notification: NSNotification) {        
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.origin.y == 0{
        self.view.frame.origin.y -= keyboardSize.height
    }
}}    

And,

@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.origin.y != 0{
        self.view.frame.origin.y = 0 
    }
} }

Solution 25 - Ios

This implementation (Swift 4) will give you the behaviour that comes closest to the default behaviour of Android. Ie: moves the view up when the active textfield is under the keyboard and moves accordingly when the user switches to another view without closing the keyboard. Remember to call setTextFieldDelegates().

public class DelegateProxy: NSObject, UITextFieldDelegate {

  private static let instance = DelegateProxies()

  weak var activeTextField: UITextField?
  var offset: CGFloat = 0
  weak var vc: UIViewController?
  var keyboardHeight: CGFloat = 0

  public static func getDelegate(root: UIViewController) -> DelegateProxies {
    instance.vc = root
    return instance
  }

  public static func getDelegate() -> DelegateProxies {
    return instance
  }

  public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
  }


  public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

    self.activeTextField = textField

    let globalPointY: CGFloat = (textField.superview?.convert(textField.frame.origin, to: nil).y ?? CGFloat(0)) + textField.frame.height


    offset = UIScreen.main.bounds.height - globalPointY

    if keyboardHeight > 0 {
        vc?.moveViewUp(offsetFromKeyboard: keyboardHeight - offset)
    }

    return true
  }
}


extension UIViewController {

  private func setTextFieldDelegates(parentView: UIView) {
    for child in parentView.subviews {
        setTextFieldDelegates(parentView: child)
        (child as? UITextField)?.delegate = DelegateProxies.getDelegate(root: self)
    }
  }

  func registerAutoResizeOnKeyboardAppear(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

  func unregisterAutoResizeOnKeyboard(){
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

  @objc func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let offsetFromKeyboard = keyboardSize.height - DelegateProxies.getDelegate().offset
        DelegateProxies.getDelegate().keyboardHeight = keyboardSize.height

        moveViewUp(offsetFromKeyboard: offsetFromKeyboard)
    }
  }

  func moveViewUp(offsetFromKeyboard: CGFloat){
    print("offset from keyboard: \(offsetFromKeyboard)")

    let moveOffset = offsetFromKeyboard + 8

    if offsetFromKeyboard > 0 {
        self.view.frame.origin.y = -moveOffset
    }

    if offsetFromKeyboard < 0 && view.frame.origin.y < 0 {
        self.view.frame.origin.y += -moveOffset
        if self.view.frame.origin.y > 0{
            self.view.frame.origin.y = 0
        }
    }
  }

  @objc func keyboardWillHide(notification: NSNotification) {
    self.view.frame.origin.y = 0
  }
}

Solution 26 - Ios

this video tutorial is the best. 7 mins long and it'll just make so much sense. Such a simple solution for when you have multiple text fields and want the scroll view to move "x" amount of pixels when that specific textfield is tapped.

https://youtu.be/VuiPGJOEBH4

Just these steps:

-Place all your textfields within a scrollview that is constrained to the edges of the view.

-Connect all the textfields and scroll view as delegates to the view controller.

-Connect all textfields and scroll view with an IBOutlet.

class ViewController: UIViewController, UITextFieldDelegate {

-Add UITextFieldDelegate protocol to your class

@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!    
@IBOutlet weak var scrollView: UIScrollView!

-Add UITextFieldDelegate methods to your swift file:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    
    textField.resignFirstResponder()
    return true
}


func textFieldDidBeginEditing(textField: UITextField) {
    
    if (textField == self.stateAddress) {
        scrollView.setContentOffset(CGPointMake(0, 25), animated: true)
    }
    else if (textField == self.zipAddress) {
        scrollView.setContentOffset(CGPointMake(0, 57), animated: true)
    }
    else if (textField == self.phoneNumber) {
        scrollView.setContentOffset(CGPointMake(0, 112), animated: true)
    }
    else if (textField == self.vetEmailAddress) {
        scrollView.setContentOffset(CGPointMake(0, 142), animated: true)
    }
}

func textFieldDidEndEditing(textField: UITextField) {
    
    scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}

The first method just activates the return button on the keyboard to dismiss the keyboard. The second is when you tap into whatever specific textfield then setting the y offset of how far your scrollview scrolls (mine is based off of the y location on my view controllers 25,57,112,142). The last says when you tap away from the keyboard the scrollview goes back to original location.

I made my view pixel perfect this way!

Solution 27 - Ios

This feature shud have come built in Ios, however we need to do externally.
Insert the below code

  • To move view when textField is under keyboard,

  • Not to move view when textField is above keyboard

  • To move View based on the height of the keyboard when needed.
    This works and tested in all cases.

    import UIKit

    class NamVcc: UIViewController, UITextFieldDelegate { @IBOutlet weak var NamTxtBoxVid: UITextField!

     var VydTxtBoxVar: UITextField!
     var ChkKeyPadDspVar: Bool = false
     var KeyPadHytVal: CGFloat!
     
     override func viewDidLoad()
     {
         super.viewDidLoad()
         
         NamTxtBoxVid.delegate = self
     }
    
     override func viewWillAppear(animated: Bool)
     {
         NSNotificationCenter.defaultCenter().addObserver(self,
             selector: #selector(TdoWenKeyPadVyd(_:)),
             name:UIKeyboardWillShowNotification,
             object: nil);
         NSNotificationCenter.defaultCenter().addObserver(self,
             selector: #selector(TdoWenKeyPadHyd(_:)),
             name:UIKeyboardWillHideNotification,
             object: nil);
     }
     
     func textFieldDidBeginEditing(TxtBoxPsgVar: UITextField)
     {
         self.VydTxtBoxVar = TxtBoxPsgVar
     }
     
     func textFieldDidEndEditing(TxtBoxPsgVar: UITextField)
     {
         self.VydTxtBoxVar = nil
     }
     
     func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
     {
         self.VydTxtBoxVar.resignFirstResponder()
         return true
     }
     
     override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
     {
         view.endEditing(true)
         super.touchesBegan(touches, withEvent: event)
     }
     
     func TdoWenKeyPadVyd(NfnPsgVar: NSNotification)
     {
         if(!self.ChkKeyPadDspVar)
         {
             self.KeyPadHytVal = (NfnPsgVar.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height
         
             var NonKeyPadAraVar: CGRect = self.view.frame
             NonKeyPadAraVar.size.height -= self.KeyPadHytVal
         
             let VydTxtBoxCenVal: CGPoint? = VydTxtBoxVar?.frame.origin
         
             if (!CGRectContainsPoint(NonKeyPadAraVar, VydTxtBoxCenVal!))
             {
                 self.ChkKeyPadDspVar = true
                 UIView.animateWithDuration(1.0,
                     animations:
                     { self.view.frame.origin.y -= (self.KeyPadHytVal)},
                     completion: nil)
             }
             else
             {
                 self.ChkKeyPadDspVar = false
             }
         }
         
     }
     
     func TdoWenKeyPadHyd(NfnPsgVar: NSNotification)
     {
         if (self.ChkKeyPadDspVar)
         {
             self.ChkKeyPadDspVar = false
             UIView.animateWithDuration(1.0,
                 animations:
                 { self.view.frame.origin.y += (self.KeyPadHytVal)},
                 completion: nil)
         }
     }
     
     override func viewDidDisappear(animated: Bool)
     {
         super.viewWillDisappear(animated)
         NSNotificationCenter.defaultCenter().removeObserver(self)
         view.endEditing(true)
         ChkKeyPadDspVar = false
     }
    

    }


|::| Sometimes View wil be down, In that case use height +/- 150 :

    NonKeyPadAraVar.size.height -= self.KeyPadHytVal + 150

    { self.view.frame.origin.y -= self.KeyPadHytVal  - 150},
                    completion: nil)

    { self.view.frame.origin.y += self.KeyPadHytVal  - 150},
                completion: nil)

Solution 28 - Ios

func keyboardWillShow(notification: NSNotification) {
    
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y = self.view.frame.height - (self.view.frame.height + keyboardSize.height)
    }
    
}

func keyboardWillHide(notification: NSNotification) {
        self.view.frame.origin.y = 0
}

it must be more stable

Solution 29 - Ios

 override func viewWillAppear(animated: Bool)
 {
 super.viewWillAppear(animated)
 
 NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
 NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
     
 }
    
 // MARK: - keyboard
 func keyboardWillShow(notification: NSNotification) 
{
            
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: keyboardSize.height, right:contentInsets.right)
                    // ...
                } else {
                    // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
                }
            } else {
                // no userInfo dictionary in notification
            }
        }
        
func keyboardWillHide(notification: NSNotification) 
{
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: 0, right:contentInsets.right)
 }
        
        

Solution 30 - Ios

Use following code for view Up on UITextField Clicked

func textFieldDidBeginEditing(textField: UITextField) {
    ViewUpanimateMoving(true, upValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
    ViewUpanimateMoving(false, upValue: 100)
}
func ViewUpanimateMoving (up:Bool, upValue :CGFloat){
    var durationMovement:NSTimeInterval = 0.3
    var movement:CGFloat = ( up ? -upValue : upValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(durationMovement)
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}

Solution 31 - Ios

I made a cocoapod to simplify the matter:

https://github.com/xtrinch/KeyboardLayoutHelper

How to use it:

Make an auto layout bottom constraint, give it a class of KeyboardLayoutConstraint in module KeyboardLayoutHelper and the pod will do the work necessary to increase it to accomodate appearing and disappearing keyboard. See example project on examples how to use it (I made two: textFields inside a scrollView, and vertically centered textFields with two basic views - login & register).

The bottom layout constraint can be of the container view, the textField itself, anything, you name it.

Solution 32 - Ios

func registerForKeyboardNotifications()
    {
        //Keyboard
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardDidHideNotification, object: nil)


    }
    func deregisterFromKeyboardNotifications(){

        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)

    }
    func keyboardWasShown(notification: NSNotification){

        let userInfo: NSDictionary = notification.userInfo!
        let keyboardInfoFrame = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue()

        let windowFrame:CGRect = (UIApplication.sharedApplication().keyWindow!.convertRect(self.view.frame, fromView:self.view))

        let keyboardFrame = CGRectIntersection(windowFrame, keyboardInfoFrame!)

        let coveredFrame = UIApplication.sharedApplication().keyWindow!.convertRect(keyboardFrame, toView:self.view)

        let contentInsets = UIEdgeInsetsMake(0, 0, (coveredFrame.size.height), 0.0)
        self.scrollViewInAddCase .contentInset = contentInsets;
        self.scrollViewInAddCase.scrollIndicatorInsets = contentInsets;
        self.scrollViewInAddCase.contentSize = CGSizeMake((self.scrollViewInAddCase.contentSize.width), (self.scrollViewInAddCase.contentSize.height))

    }
    /**
     this method will fire when keyboard was hidden

     - parameter notification: contains keyboard details
     */
    func keyboardWillBeHidden (notification: NSNotification) {

        self.scrollViewInAddCase.contentInset = UIEdgeInsetsZero
        self.scrollViewInAddCase.scrollIndicatorInsets = UIEdgeInsetsZero

    }

Solution 33 - Ios

swift 3.0 insert in viewDidLoad(), this->

{

view.addSubview(Your_messageInputConteinerView)

    view.addConstraintWithFormat(format: "H:|[v0]|", views:Your_messageInputConteinerView)

    view.addConstraintWithFormat(format: "V:[v0(48)]", views:Your_messageInputConteinerView)

NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification(notification:)), name: .UIKeyboardWillHide, object: nil)

bottomConstraint = NSLayoutConstraint(item: Your_messageInputConteinerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)

view.addConstraint(bottomConstraint!)

}

func handleKeyboardNotification(notification:Notification){

if let userInfo = notification.userInfo {

    if let keyBoardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue{

        print(keyBoardFrame)

        if bottomConstraint?.constant != CGFloat(0) {
                bottomConstraint?.constant = 0
                return
            }
     bottomConstraint?.constant = -keyBoardFrame.height
                           or
        self.view.frame.origin.y = -keyBoardFrame.height
    }
}

}

Solution 34 - Ios

i've read answers and solved my problem by this lines of code:

class ViewController: UIViewController, UITextFieldDelegate {

  @IBOutlet weak var titleField: UITextField!
  @IBOutlet weak var priceField: UITextField!
  @IBOutlet weak var detailsField: UTtextField!

  override func viewDidLoad() {
   super.viewDidLoad()
// Do not to forget to set the delegate otherwise the textFieldShouldReturn(_:)
// won't work and the keyboard will never be hidden.
   priceField.delegate = self
   titleField.delegate = self
   detailsField.delegate = self

   NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow),
 name: NSNotification.Name.UIKeyboardWillShow, object: nil)

   NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide),
 name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

   func textFieldShouldReturn(_ textField: UITextField) -> Bool {
      self.view.endEditing(true)
      return false
   }

 func keyboardWillShow(notification: NSNotification) {
   var translation:CGFloat = 0
   if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
     if detailsField.isEditing{
       translation = CGFloat(-keyboardSize.height)
     }else if priceField.isEditing{
       translation = CGFloat(-keyboardSize.height / 3.8)
     }
   }
    UIView.animate(withDuration: 0.2) {
   self.view.transform = CGAffineTransform(translationX: 0, y: translation)
    }
  }


 func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2) {
     self.view.transform = CGAffineTransform(translationX: 0, y: 0)
    } 
  }
}

I have a few UITextFields and want the view to move up differently depending on which textField is tapped.

Solution 35 - Ios

if you are like me who has tried all the above solutions and still your problem is not solved, I have a got a great solution for you that works like a charm. First I want clarify few things about some of solutions mentioned above.

  1. In my case IQkeyboardmanager was working only when there is no auto layout applied on the elements, if it is applied then IQkeyboard manager will not work the way we think.
  2. Same thing with upward movement of self.view.
  3. i have wriiten a objective c header with a swift support for pushing UITexfield upward when user clicks on it, solving the problem of keyboard covering the UITextfield : https://github.com/coolvasanth/smart_keyboard.
  4. One who has An intermediate or higher level in iOS app development can easily understand the repository and implement it. All the best

Solution 36 - Ios

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y != 0{
           // self.view.frame.origin.y += keyboardSize.height
            self.view.frame.origin.y = 0
        }
    }
}

Solution 37 - Ios

Simpelst Method In Swift 4 enter image description here

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    
    @IBOutlet var myTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        myTextField.resignFirstResponder()
    }
    
    func keyboardWillShow(notification: NSNotification) {
        // let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]
        // print("duration",duration)
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight : Int = Int(keyboardSize.height)
            print("keyboardWillShow",keyboardHeight)
            if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
                moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.43, up: true)
            }else{
                UserDefaults.standard.set(keyboardHeight, forKey: "keyboardHeight")
                moveTextField(myTextField, moveDistance: -keyboardHeight, moveDuration: 0.43, up: true)
            }
        }
    }
    
    func keyboardWillHide(notification: NSNotification){
        if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
            moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.25, up: false)
        }
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    
    func moveTextField(_ textField: UITextField, moveDistance: Int, moveDuration: Double, up: Bool) {
        let movement: CGFloat = CGFloat(up ? moveDistance : -moveDistance)
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(moveDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }

}

You Can Also Move Up And Down Only UITextFiled Not Whole Screen(UIView).
With Using This Method.

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)

And

   @objc func keyboardWillChange(notification: NSNotification) {
        
        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.origin.y - curFrame.origin.y
        
        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.textField.frame.origin.y+=deltaY
            
        },completion: nil)
    }

Solution 38 - Ios

I've need to move a UIView in swift 4 when keyboard opens and closes. and all of the answers couldn't help me. because height of keyboard changes when emojis open. so my code is :

@objc func keyboardWillShow(sender: NSNotification) {
    
    if let keyboardFrame: NSValue = sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
        
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
        
        if(self.oldHeight == keyboardHeight){
            self.sendingView.frame.origin.y -= keyboardHeight
            self.oldHeight = keyboardHeight
        }
        else{
            self.sendingView.frame.origin.y += self.oldHeight
            self.sendingView.frame.origin.y -= keyboardHeight
            self.oldHeight = keyboardHeight
        }
    }
}

@objc func keyboardWillHide(sender: NSNotification) {
    
    if let keyboardFrame: NSValue = sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
        
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
        
        self.sendingView.frame.origin.y += keyboardHeight
        
    }
}

and in viewDidLoad() :

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);

self.oldHeight = CGFloat() and defines as field at the top of class.

Solution 39 - Ios

Swift 4.1

 override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height   //can adjust as keyboardSize.height-(any number 30 or 40)
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

Solution 40 - Ios

Moving origin of the view is a naive approach.

Here is the better solution: Adjust the height of the view when the keyboard appears.

let viewHeight = self.view.frame.height

    override func viewDidLoad() {
        super.viewDidLoad()
        
        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 keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.height == self.viewHeight{
                self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height - keyboardSize.height)
            }
          
        }
    }

    @objc func keyboardWillHide(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

            self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height + keyboardSize.height)
        }
    }

Solution 41 - Ios

Since there were no answer on how to do this in Combine, here is the approach i used.

  1. We create a publisher to listen to both Notifications, show and hide.
  2. For show we get the frame of the keyboard from the notifications userInfo and check if the current active responder is contained in it. If it's covered return keyboard frame height. If it is not covered return 0, we don't want to move the frame. For the hide notification we simply return 0.
private var keyboardHeightPublisher: AnyPublisher<CGFloat, Never> {
    Publishers.Merge(
        NotificationCenter.default
            .publisher(for: UIResponder.keyboardWillShowNotification)
            .compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect }
            .map { $0.intersects(self.view.firstResponder!.frame) ? $0.height : 0 }
            .map { $0 * -1 },
        NotificationCenter.default
            .publisher(for: UIResponder.keyboardWillHideNotification)
            .map { _ in CGFloat(0) }
    ).eraseToAnyPublisher()
}

In the viewDidLoad we simply subscribe to the publisher changing the views frame accordingly.

override func viewDidLoad() {
    super.viewDidLoad()

    keyboardHeightPublisher.sink{ [weak self] height in
        self?.view.frame.origin.y = height
    }.store(in: &cancelables)
}

EDIT
Be careful! If the firstResponder is in a subview, you have to calculate the frame corresponding to the whole screen to check if they actually intersect.
Example:

let myViewGlobalFrame = myView.convert(myView.frame, to: parentView)

Solution 42 - Ios

works for me

override func viewDidLoad() {

        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

 var isScroll = false


@objc func keyboardWillShow(sender: NSNotification) {
    if( !isScroll  ){
        self.view.frame.origin.y -= 150
        isScroll = true
    }
}
@objc func keyboardWillHide(sender: NSNotification) {
    if( isScroll  ){
        self.view.frame.origin.y += 150
        isScroll = false
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlex CatchpoleView Question on Stackoverflow
Solution 1 - IosBorisView Answer on Stackoverflow
Solution 2 - IosgammachillView Answer on Stackoverflow
Solution 3 - IosDan BeaulieuView Answer on Stackoverflow
Solution 4 - IosweegeeView Answer on Stackoverflow
Solution 5 - IosscipianneView Answer on Stackoverflow
Solution 6 - Iosuser3677173View Answer on Stackoverflow
Solution 7 - IosSaifan NadafView Answer on Stackoverflow
Solution 8 - IosAmr HossamView Answer on Stackoverflow
Solution 9 - IosAli Ihsan URALView Answer on Stackoverflow
Solution 10 - IosIvan Le HjelmelandView Answer on Stackoverflow
Solution 11 - IosAntziView Answer on Stackoverflow
Solution 12 - IosPavle MijatovicView Answer on Stackoverflow
Solution 13 - IosQuentin NView Answer on Stackoverflow
Solution 14 - IosGrant ParkView Answer on Stackoverflow
Solution 15 - IosingcontiView Answer on Stackoverflow
Solution 16 - IosJerry ChongView Answer on Stackoverflow
Solution 17 - IosCelil BozkurtView Answer on Stackoverflow
Solution 18 - IosMaulik PatelView Answer on Stackoverflow
Solution 19 - IosRbarView Answer on Stackoverflow
Solution 20 - IosGene LoparcoView Answer on Stackoverflow
Solution 21 - IosVah.SahView Answer on Stackoverflow
Solution 22 - IosMr. XcoderView Answer on Stackoverflow
Solution 23 - IosRohit SharmaView Answer on Stackoverflow
Solution 24 - IosEray AlparslanView Answer on Stackoverflow
Solution 25 - Iosravindu1024View Answer on Stackoverflow
Solution 26 - Iosbme003View Answer on Stackoverflow
Solution 27 - IosSujay U NView Answer on Stackoverflow
Solution 28 - IosHadevs PlayView Answer on Stackoverflow
Solution 29 - IosHimali ShahView Answer on Stackoverflow
Solution 30 - IosJugal K BalaraView Answer on Stackoverflow
Solution 31 - IosxtrinchView Answer on Stackoverflow
Solution 32 - IosKamalkumar.EView Answer on Stackoverflow
Solution 33 - IosAnton RussiaView Answer on Stackoverflow
Solution 34 - IosFedya GrabView Answer on Stackoverflow
Solution 35 - IosVasanthView Answer on Stackoverflow
Solution 36 - IosPuji WahonoView Answer on Stackoverflow
Solution 37 - IosZAFAR007View Answer on Stackoverflow
Solution 38 - IosMHSFisherView Answer on Stackoverflow
Solution 39 - IosAsfar Hussain SiddiquiView Answer on Stackoverflow
Solution 40 - IosAditya kumrawatView Answer on Stackoverflow
Solution 41 - IosDeitschView Answer on Stackoverflow
Solution 42 - IosJuan David CardonaView Answer on Stackoverflow