Mueva una vista hacia arriba solo cuando el teclado cubra un campo de entrada

Estoy tratando de construir una pantalla de entrada para el iPhone. La pantalla tiene una cantidad de campos de entrada. La mayoría de ellos en la parte superior de la pantalla, pero dos campos están en la parte inferior. Cuando el usuario intente editar el texto en la parte inferior de la pantalla, el teclado aparecerá y cubrirá la pantalla. Encontré una solución simple para mover la pantalla cuando esto sucede, pero el resultado es que la pantalla siempre se mueve hacia arriba y los campos en la parte superior de la pantalla se mueven fuera del scope cuando el usuario intenta editarlos.

¿Hay alguna manera de hacer que la pantalla solo se mueva cuando se editan los campos inferiores?

He usado este código que encontré aquí :

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(sender: NSNotification) { self.view.frame.origin.y -= 150 } func keyboardWillHide(sender: NSNotification) { self.view.frame.origin.y += 150 } 

Su problema está bien explicado en este documento por Apple . El código de ejemplo en esta página (en el Listing 4-1 ) hace exactamente lo que necesita, desplazará su vista solo cuando la edición actual deba estar debajo del teclado. Solo necesita poner sus controles necesarios en una vista de desplazamiento. El único problema es que este es Objective-C y creo que lo necesitas en Swift … así que … aquí está:

Declarar una variable

 var activeField: UITextField? 

luego agregue estos métodos

  func registerForKeyboardNotifications() { //Adding notifies on keyboard appearing NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) } func deregisterFromKeyboardNotifications() { //Removing notifies on keyboard appearing NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } func keyboardWasShown(notification: NSNotification) { //Need to calculate keyboard exact size due to Apple suggestions self.scrollView.scrollEnabled = true var info : NSDictionary = notification.userInfo! var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0) self.scrollView.contentInset = contentInsets self.scrollView.scrollIndicatorInsets = contentInsets var aRect : CGRect = self.view.frame aRect.size.height -= keyboardSize!.height if let activeFieldPresent = activeField { if (!CGRectContainsPoint(aRect, activeField!.frame.origin)) { self.scrollView.scrollRectToVisible(activeField!.frame, animated: true) } } } func keyboardWillBeHidden(notification: NSNotification) { //Once keyboard disappears, restre original positions var info : NSDictionary = notification.userInfo! var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0) self.scrollView.contentInset = contentInsets self.scrollView.scrollIndicatorInsets = contentInsets self.view.endEditing(true) self.scrollView.scrollEnabled = false } func textFieldDidBeginEditing(textField: UITextField!) { activeField = textField } func textFieldDidEndEditing(textField: UITextField!) { activeField = nil } 

Asegúrese de declarar su ViewController como UITextFieldDelegate y establecer los delegates correctos en sus métodos de inicialización: ej:

 self.you_text_field.delegate = self 

Y recuerde llamar a registerForKeyboardNotifications en viewInit y deregisterFromKeyboardNotifications al salir.

Editar / Actualizar: syntax de Swift 3.0

 func registerForKeyboardNotifications(){ //Adding notifies on keyboard appearing NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func deregisterFromKeyboardNotifications(){ //Removing notifies on keyboard appearing NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func keyboardWasShown(notification: NSNotification){ //Need to calculate keyboard exact size due to Apple suggestions self.scrollView.isScrollEnabled = true var info = notification.userInfo! let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0) self.scrollView.contentInset = contentInsets self.scrollView.scrollIndicatorInsets = contentInsets var aRect : CGRect = self.view.frame aRect.size.height -= keyboardSize!.height if let activeField = self.activeField { if (!aRect.contains(activeField.frame.origin)){ self.scrollView.scrollRectToVisible(activeField.frame, animated: true) } } } func keyboardWillBeHidden(notification: NSNotification){ //Once keyboard disappears, restre original positions var info = notification.userInfo! let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0) self.scrollView.contentInset = contentInsets self.scrollView.scrollIndicatorInsets = contentInsets self.view.endEditing(true) self.scrollView.isScrollEnabled = false } func textFieldDidBeginEditing(_ textField: UITextField){ activeField = textField } func textFieldDidEndEditing(_ textField: UITextField){ activeField = nil } 

Aquí está Mi 2 centavos:

Has probado: https://github.com/hackiftekhar/IQKeyboardManager

Extremadamente fácil de instalar Swift u Objective-C.

Aquí cómo funciona:

IQKeyboardManager (Swift): – IQKeyboardManagerSwift está disponible a través de CocoaPods, para instalarlo simplemente agregue la siguiente línea a su Podfile: (# 236)

 pod 'IQKeyboardManagerSwift' 

En AppDelegate.swift, solo importa IQKeyboardManagerSwift framework y habilita IQKeyboardManager.

 import IQKeyboardManagerSwift @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { IQKeyboardManager.sharedManager().enable = true return true } } 

Y eso es todo. ¡Fácil!

El que encontré para funcionar perfectamente para mí fue este:

 func textFieldDidBeginEditing(textField: UITextField) { if textField == email || textField == password { animateViewMoving(true, moveValue: 100) } } func textFieldDidEndEditing(textField: UITextField) { if textField == email || textField == password { animateViewMoving(false, moveValue: 100) } } func animateViewMoving (up:Bool, moveValue :CGFloat){ let movementDuration:NSTimeInterval = 0.3 let movement:CGFloat = ( up ? -moveValue : moveValue) UIView.beginAnimations("animateView", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() } 

También puede cambiar los valores de altura. Elimine la “instrucción if” si desea usarla para todos los campos de texto.

Incluso puede usar esto para todos los controles que requieren la entrada del usuario como TextView.

¿Hay alguna manera de hacer que la pantalla solo se mueva cuando se editan los campos inferiores ?

Tuve un problema similar y encontré una solución bastante sencilla sin usar un scrollView, y en su lugar usando sentencias if dentro del tecladoWillShow / Hide methods.

 func keyboardWillShow(notification: NSNotification) { if bottomText.editing{ self.view.window?.frame.origin.y = -1 * getKeyboardHeight(notification) } } func keyboardWillHide(notification: NSNotification) { if self.view.window?.frame.origin.y != 0 { self.view.window?.frame.origin.y += getKeyboardHeight(notification) } } 

Esta fue una buena solución para mí porque solo tenía dos campos de texto.

Cambia la vista completa: solo cuando se editan ciertos campos de texto (texto de abajo)

Desplaza toda la vista hacia abajo: solo cuando la vista no está en la ubicación original

¿Por qué no implementar esto en un UITableViewController en su lugar? El teclado no ocultará ningún campo de texto cuando se muestre.

Swift 3 con extensión

  1. agregue los botones en un contenedor
  2. conectar la restricción de fondo del contenedor con IBOutlet containerBtmConstrain
  3. inViewDidLoad

     self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain self.watchForKeyboard() 
  4. agregue la siguiente extensión

     private var xoAssociationKeyForBottomConstrainInVC: UInt8 = 0 extension UIViewController { var containerDependOnKeyboardBottomConstrain :NSLayoutConstraint! { get { return objc_getAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC) as? NSLayoutConstraint } set(newValue) { objc_setAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) } } func watchForKeyboard () { NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown(notification:)), name:NSNotification.Name.UIKeyboardWillShow, object: nil); NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name:NSNotification.Name.UIKeyboardWillHide, object: nil); } func keyboardWasShown(notification: NSNotification) { let info = notification.userInfo! let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue UIView.animate(withDuration: 0.3, animations: { () -> Void in self.containerDependOnKeyboardBottomConstrain.constant = keyboardFrame.height self.view.layoutIfNeeded() }) } func keyboardWillHide(notification: NSNotification) { UIView.animate(withDuration: 0.3, animations: { () -> Void in self.containerDependOnKeyboardBottomConstrain.constant = 0 self.view.layoutIfNeeded() }) } } 

Creo que esta cláusula es incorrecta:

 if (!CGRectContainsPoint(aRect, activeField!.frame.origin)) 

Si bien el origen de activeField puede estar por encima del teclado, es posible que maxY no …

Crearía un punto “máximo” para activeField y verificaría si eso está en el teclado Rect.

Uso SwiftLint, que tenía algunos problemas con el formato de la respuesta aceptada. Específicamente:

no hay espacio antes del colon, no se usa la fuerza, prefiere UIEdgeInset (arriba: etc … en lugar de UIEdgeInsetMake).

así que estas son las actualizaciones de Swift 3

 func registerForKeyboardNotifications() { //Adding notifies on keyboard appearing NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func deregisterFromKeyboardNotifications() { //Removing notifies on keyboard appearing NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func keyboardWasShown(notification: NSNotification) { //Need to calculate keyboard exact size due to Apple suggestions scrollView?.isScrollEnabled = true var info = notification.userInfo! if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size { let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0) scrollView?.contentInset = contentInsets scrollView?.scrollIndicatorInsets = contentInsets var aRect: CGRect = self.view.frame aRect.size.height -= keyboardSize.height if let activeField = self.activeField { if !aRect.contains(activeField.frame.origin) { self.scrollView.scrollRectToVisible(activeField.frame, animated: true) } } } } func keyboardWillBeHidden(notification: NSNotification) { //Once keyboard disappears, restre original positions var info = notification.userInfo! if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size { let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize.height, right: 0.0) scrollView?.contentInset = contentInsets scrollView?.scrollIndicatorInsets = contentInsets } view.endEditing(true) scrollView?.isScrollEnabled = false } func textFieldDidBeginEditing(_ textField: UITextField) { activeField = textField } func textFieldDidEndEditing(_ textField: UITextField) { activeField = nil } 

Aquí está mi versión después de leer la documentación proporcionada por Apple y las publicaciones anteriores. Una cosa que noté es que textView no se manejó cuando estaba cubierto por el teclado. Desafortunadamente, la documentación de Apple no funcionará porque, por alguna razón, el teclado se llama DESPUÉS de que se invoque textViewDidBeginEditing. Manejé esto llamando a un método central que verifica si se muestra el teclado Y si se está editando un textView o textField. De esta forma, el proceso solo se activa cuando existen AMBAS condiciones.

Otro punto con textViews es que su altura puede ser tal que el teclado recorta la parte inferior de textView y no se ajustaría si el punto superior izquierdo estuviera a la vista. Entonces, el código que escribí realmente toma el punto Inferior-Izquierdo referenciado en pantalla de cualquier textView o textField y ve si cae en las coordenadas referidas a la pantalla del teclado presentado, lo que implica que el teclado cubre una parte del mismo.

 let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil) if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY))) { // scroll textView/textField into view } 

Si está usando un controlador de navegación, la subclase también establece el ajuste automático de la vista de desplazamiento para las inserciones en falso.

 self.automaticallyAdjustsScrollViewInsets = false 

Recorre cada textView y textField para configurar delegates para el manejo

  for view in self.view.subviews { if view is UITextView { let tv = view as! UITextView tv.delegate = self } else if view is UITextField { let tf = view as! UITextField tf.delegate = self } } 

Simplemente configure su clase base a la subclase creada aquí para obtener resultados.

 import UIKit class ScrollingFormViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate { var activeFieldRect: CGRect? var keyboardRect: CGRect? var scrollView: UIScrollView! override func viewDidLoad() { self.automaticallyAdjustsScrollViewInsets = false super.viewDidLoad() // Do any additional setup after loading the view. self.registerForKeyboardNotifications() for view in self.view.subviews { if view is UITextView { let tv = view as! UITextView tv.delegate = self } else if view is UITextField { let tf = view as! UITextField tf.delegate = self } } scrollView = UIScrollView(frame: self.view.frame) scrollView.scrollEnabled = false scrollView.showsVerticalScrollIndicator = false scrollView.showsHorizontalScrollIndicator = false scrollView.addSubview(self.view) self.view = scrollView } override func viewDidLayoutSubviews() { scrollView.sizeToFit() scrollView.contentSize = scrollView.frame.size super.viewDidLayoutSubviews() } deinit { self.deregisterFromKeyboardNotifications() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func registerForKeyboardNotifications() { //Adding notifies on keyboard appearing NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWasShown), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil) } func deregisterFromKeyboardNotifications() { //Removing notifies on keyboard appearing NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } func keyboardWasShown(notification: NSNotification) { let info : NSDictionary = notification.userInfo! keyboardRect = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() adjustForKeyboard() } func keyboardWillBeHidden(notification: NSNotification) { keyboardRect = nil adjustForKeyboard() } func adjustForKeyboard() { if keyboardRect != nil && activeFieldRect != nil { let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil) if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY))) { scrollView.scrollEnabled = true let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardRect!.size.height, 0.0) scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets scrollView.scrollRectToVisible(activeFieldRect!, animated: true) } } else { let contentInsets : UIEdgeInsets = UIEdgeInsetsZero scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets scrollView.scrollEnabled = false } } func textViewDidBeginEditing(textView: UITextView) { activeFieldRect = textView.frame adjustForKeyboard() } func textViewDidEndEditing(textView: UITextView) { activeFieldRect = nil adjustForKeyboard() } func textFieldDidBeginEditing(textField: UITextField) { activeFieldRect = textField.frame adjustForKeyboard() } func textFieldDidEndEditing(textField: UITextField) { activeFieldRect = nil adjustForKeyboard() } } 

En el siguiente ejemplo, solo estoy moviendo la vista hacia arriba cuando comienzo a editar el txtLastName o txtCity. Creé la variable keyboardActive porque la vista puede avanzar 2 veces si hago clic en txtLastName y luego en txtCity.

Eche un vistazo y vea si funciona para usted.

 class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet weak var txtFirstName: UITextField! @IBOutlet weak var txtLastName: UITextField! @IBOutlet weak var txtCity: UITextField! var keyboardActive = false override func viewDidLoad() { super.viewDidLoad() self.txtFirstName.delegate = self self.txtLastName.delegate = self self.txtCity.delegate = self } func textFieldDidBeginEditing(textField: UITextField) { if textField != self.txtFirstName && keyboardActive == false { self.view.frame.origin.y -= 165 self.keyboardActive = true } } func textFieldShouldEndEditing(textField: UITextField) -> Bool { if textField != self.txtFirstName && keyboardActive == true { self.view.frame.origin.y += 165 self.keyboardActive = false } return true } func textFieldShouldReturn(textField: UITextField) -> Bool { self.view.endEditing(true) return false } } 

Ya se han dado respuestas impresionantes, pero esta es una forma diferente de lidiar con esta situación (usando Swift 3x ):

En primer lugar, llame al siguiente método en viewWillAppear()

 func registerForKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: NSNotification.Name.UIKeyboardDidShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } 

Ahora tome una IBOutlet de las principales restricciones de UIViewcontroller de su UIViewcontroller esta manera: (aquí la UIView es la subvista de UIScrollView que significa que debe tener UIScrollView para todas sus subViews )

 @IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint! 

Y una variable más como seguir y agregar un delegado, es decir, UITextFieldDelegate :

 var activeTextField = UITextField() //This is to keep the reference of UITextField currently active 

Después de eso, aquí está la parte mágica, solo pega este fragmento a continuación:

 func keyboardWasShown(_ notification: Notification) { let keyboardInfo = notification.userInfo as NSDictionary? //print(keyboardInfo!) let keyboardFrameEnd: NSValue? = (keyboardInfo?.value(forKey: UIKeyboardFrameEndUserInfoKey) as? NSValue) let keyboardFrameEndRect: CGRect? = keyboardFrameEnd?.cgRectValue if activeTextField.frame.origin.y + activeTextField.frame.size.height + 10 > (keyboardFrameEndRect?.origin.y)! { UIView.animate(withDuration: 0.3, delay: 0, options: .transitionFlipFromTop, animations: {() -> Void in //code with animation //Print some stuff to know what is actually happening //print(self.activeTextField.frame.origin.y) //print(self.activeTextField.frame.size.height) //print(self.activeTextField.frame.size.height) self.loginViewTopConstraint.constant = -(self.activeTextField.frame.origin.y + self.activeTextField.frame.size.height - (keyboardFrameEndRect?.origin.y)!) - 30.0 self.view.layoutIfNeeded() }, completion: {(_ finished: Bool) -> Void in //code for completion }) } } func keyboardWillBeHidden(_ notification: Notification) { UIView.animate(withDuration: 0.3, animations: {() -> Void in self.loginViewTopConstraint.constant = self.view.frame.origin.y self.view.layoutIfNeeded() }) } //MARK: textfield delegates func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { activeTextField = textField return true } func textFieldShouldReturn(_ textField: UITextField) -> Bool { switch textField { case YOUR_TEXTFIELD_ONE: YOUR_TEXTFIELD_TWO.becomeFirstResponder() break case YOUR_TEXTFIELD_TWO: YOUR_TEXTFIELD_THREE.becomeFirstResponder() break default: textField.resignFirstResponder() break } return true } 

Ahora el último fragmento:

 //Remove Keyboard Observers override func viewWillDisappear(_ animated: Bool) { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) } 

No olvide asignar delegates a todos sus UITextField s en UIStoryboard

¡Buena suerte!

Sintaxis de Swift 3:

 func textFieldDidBeginEditing(_ textField: UITextField) { // add if for some desired textfields animateViewMoving(up: true, moveValue: 100) } func textFieldDidEndEditing(_ textField: UITextField) { // add if for some desired textfields animateViewMoving(up: false, moveValue: 100) } func animateViewMoving (up:Bool, moveValue :CGFloat){ textFieldDidEndEditing(_ textField: UITextField) { let movementDuration:TimeInterval = 0.5 let movement:CGFloat = ( up ? -moveValue : moveValue) UIView.beginAnimations("animateView", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement) UIView.commitAnimations() } 

este es un buen método para obtener lo que quiere, puede agregar condiciones “si” para ciertos campos de texto, pero este tipo funciona para todos … Espero que pueda ser útil para todos

Simplemente use esta extensión para mover cualquier UIView cuando se presenta el teclado.

  extension UIView { func bindToKeyboard(){ NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil) } @objc func keyboardWillChange(_ notification: NSNotification){ let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt let beginningFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue let deltaY = endFrame.origin.y - beginningFrame.origin.y UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: { self.frame.origin.y += deltaY }, completion: nil) } } 

Luego en tu viewdidload vincula tu vista al teclado

 UiView.bindToKeyboard() 

“Olvidé mencionar que soy nuevo en Swift 🙁 ¿Cuál sería la syntax correcta para verificar esto? (¿Cómo obtengo el nombre del campo en esta función?)”

Okay . Primero confirme el protocolo UITextFieldDelegate

 class YourClass:UITextFieldDelegate 

Luego implementa la función

 func textFieldDidBeginEditing(textField: UITextField!) { if textField == txtOne { println("TextOne") } if textField == txtTwo { println("TextTwo") } } 

Debe tener en cuenta que el enfoque adecuado es utilizar una vista de desplazamiento y colocar la vista que se debe desplazar hacia arriba o hacia abajo dentro de la vista de desplazamiento y manejar los eventos del teclado en consecuencia

Este código se mueve hacia arriba en el campo de texto que está editando para que pueda verlo en Swift 3 y para esta respuesta también debe convertir su vista en UITextFieldDelegate:

 var moveValue: CGFloat! var moved: Bool = false var activeTextField = UITextField() func textFieldDidBeginEditing(_ textField: UITextField) { self.activeTextField = textField } func textFieldDidEndEditing(_ textField: UITextField) { if moved == true{ self.animateViewMoving(up: false, moveValue: moveValue ) moved = false } } func animateViewMoving (up:Bool, moveValue :CGFloat){ let movementDuration:TimeInterval = 0.3 let movement:CGFloat = ( up ? -moveValue : moveValue) UIView.beginAnimations("animateView", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement) UIView.commitAnimations() } 

Y luego en viewDidLoad:

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

Qué llamadas (fuera de viewDidLoad):

 func keyboardWillShow(notification: Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { let keyboardHeight = keyboardSize.height if (view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height < keyboardHeight{ moveValue = keyboardHeight - ((view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height) self.animateViewMoving(up: true, moveValue: moveValue ) moved = true } } } 

Swift 3

 @IBOutlet var scrollView: UIScrollView! @IBOutlet var edtEmail: UITextField! @IBOutlet var bottomTextfieldConstrain: NSLayoutConstraint! // < - this guy is the constrain that connect the bottom of textField to lower object or bottom of page! @IBAction func edtEmailEditingDidBegin(_ sender: Any) { self.bottomTextfieldConstrain.constant = 200 let point = CGPoint(x: 0, y: 200) scrollView.contentOffset = point } @IBAction func edtEmailEditingDidEnd(_ sender: Any) { self.bottomTextfieldConstrain.constant = 50 } 

El awser aceptado es casi perfecto. Pero necesito usar UIKeyboardFrameEndUserInfoKey lugar de UIKeyboardFrameBeginUserInfoKey, porque este último devuelve keyborad height 0. Y cambia el punto de hittest a bottom no origin.

  var aRect : CGRect = self.view.frame aRect.size.height -= keyboardSize!.height if let activeField = self.activeField { var point = activeField.frame.origin point.y += activeField.frame.size.height if (!aRect.contains(point)){ self.scrollView.scrollRectToVisible(activeField.frame, animated: true) } } 

En primer lugar, declare una variable para identificar su UITextField activo.

Paso 1:-

Al igual que var activeTextField: UITextField ?

Paso 2: – Después de esto, agrega estas dos líneas en 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) 

Paso 3:-

Ahora defina estos dos métodos en su clase de controlador.

 func keyboardWillShow(_ notification: NSNotification) { self.scrollView.isScrollEnabled = true var info = notification.userInfo! let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0) self.scrollView.contentInset = contentInsets self.scrollView.scrollIndicatorInsets = contentInsets var aRect : CGRect = self.view.frame aRect.size.height -= keyboardSize!.height if let activeField = self.activeField { if (!aRect.contains(activeField.frame.origin)){ self.scrollView.scrollRectToVisible(activeField.frame, animated: true) } } } func keyboardWillHide(_ notification: NSNotification) { let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0) self.scrollView.contentInset = contentInsets self.scrollView.scrollIndicatorInsets = contentInsets self.view.endEditing(true) self.scrollView.isScrollEnabled = true } func textFieldDidBeginEditing(_ textField: UITextField){ activeField = textField } func textFieldDidEndEditing(_ textField: UITextField){ activeField = nil } 

Swift 4 actualizó mi solución

con animación de restricción en el teclado show / hide, enjoy.

 import Foundation import UIKit class PhoneController: UIViewController, UITextFieldDelegate{ var phoneLayoutYConstraint: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) phoneField.delegate = self view.addSubview(phoneField) NSLayoutConstraint.activate([phoneField.heightAnchor.constraint(equalToConstant: 50), phoneField.centerXAnchor.constraint(equalTo: view.centerXAnchor), phoneField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), phoneField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)]) phoneLayoutYConstraint = NSLayoutConstraint(item: phoneField, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0) phoneLayoutYConstraint?.isActive = true } let phoneField: UITextField = { let text = UITextField() text.translatesAutoresizingMaskIntoConstraints = false text.keyboardType = .numberPad text.font = UIFont.systemFont(ofSize: 30) text.layer.cornerRadius = 5.0 text.layer.masksToBounds = true text.layer.borderColor = UIColor.darkGray.cgColor text.layer.borderWidth = 2.0 return text }() override func viewDidDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self) } func textFieldDidBeginEditing(_ textField: UITextField) { } func textFieldDidEndEditing(_ textField: UITextField) { } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } @objc func handleKeyBoardNotification(_ notification: NSNotification) { if let info = notification.userInfo { let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let isKeyBoardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow var aRect : CGRect = self.phoneField.frame aRect.size.height -= keyboardSize!.height phoneLayoutYConstraint?.constant = isKeyBoardShowing ? -keyboardSize!.height : 0 UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: { self.view.layoutIfNeeded() }, completion: { (boo) in }) } } } 

Swift 4

You Can Easily Move Up And Down UITextField With Keyboard With Animation

enter image description here

 import UIKit class ViewController: UIViewController { @IBOutlet var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil) } override func touchesBegan(_ touches: Set, with event: UIEvent?) { textField.resignFirstResponder() } @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) } 

Swift 4.2

My solution will (vertically) center the view on a UITextField if its position is under the keyboard.

Step 1: Create new swift file and copy-paste UIViewWithKeyboard class.
Step 2: In Interface Builder set it as a Custom Class for your top most UIView .

 import UIKit class UIViewWithKeyboard: UIView { @IBInspectable var offsetMultiplier: CGFloat = 0.75 private var keyboardHeight = 0 as CGFloat private weak var activeTextField: UITextField? override func awakeFromNib() { super.awakeFromNib() NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.textDidBeginEditing), name: UITextField.textDidBeginEditingNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) } @objc func textDidBeginEditing(_ notification: NSNotification) { self.activeTextField = notification.object as? UITextField } @objc func keyboardWillShow(_ notification: Notification) { if let frameValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { keyboardHeight = frameValue.cgRectValue.size.height if let textField = self.activeTextField { let offset = textField.frame.maxY < frame.maxY - keyboardHeight ? 0 : textField.frame.maxY - (frame.maxY - keyboardHeight) * offsetMultiplier self.setView(offset: offset) } } } @objc func keyboardWillHide(_ notification: NSNotification) { self.setView(offset: 0) } func setView(offset: CGFloat) { UIView.animate(withDuration: 0.25) { self.bounds.origin.y = offset } } }