teclado tamaño separado pro partido mover juntar hacia dividio dividido configurar como cambiar aumentar abajo ios swift keyboard xcode6

ios - tamaño - Mueve una vista hacia arriba solo cuando el teclado cubre un campo de entrada



teclado ipad separado como juntar (23)

Estoy tratando de construir una pantalla de entrada para el iPhone. La pantalla tiene varios 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 intenta editar el texto en la parte inferior de la pantalla, aparecerá el teclado y cubrirá la pantalla. Encontré una solución simple para mover la pantalla hacia arriba 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 quedan fuera del alcance 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é here :

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 }


¿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 scrollView, y en su lugar usando if en los métodos keyboardWillShow / Hide.

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.

Desplaza toda la vista hacia arriba: solo cuando se editan ciertos campos de texto (bottomText)

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


para rápido 4.2.

Esto se aplicará a cualquier forma. No hay necesidad de scrollview. no te olvides de establecer delegado.

Hacer una var de uitextfield

var clickedTextField = UITextField()

En su vista, cargamos

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

Conozca el campo de texto en el que se hizo clic. probablemente tenga campos de texto en toda la pantalla.

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

Compruebe si el teclado está cubriendo el campo de texto o no.

@objc func keyboardWillShow(sender: NSNotification,_ textField : UITextField) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { if clickedTextField.frame.origin.y > keyboardSize.origin.y { self.view.frame.origin.y = keyboardSize.origin.y - clickedTextField.center.y - 20 } } } @objc func keyboardWillHide(sender: NSNotification) { self.view.frame.origin.y = 0 }

Regresar al teclado cerrado

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

ACTUALIZACIÓN: NSNotification.Name.UIKeyboardWillShow y NSNotification.Name.UIKeyboardWillHide se renombran a UIResponder.keyboardWillShowNotification y UIResponder.keyboardWillHideNotification respectivamente.


Este código sube el campo de texto que está editando para que pueda verlo en Swift 3 para esta respuesta, también debe hacer que su vista sea un 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 } } }


La respuesta aceptada es casi perfecta. Pero necesito usar en UIKeyboardFrameEndUserInfoKey lugar de UIKeyboardFrameBeginUserInfoKey, porque este último devuelve la altura 0 del keyborad. Y cambia el punto de prueba al fondo, no el origen.

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


Para Swift 4.2

Este código le permitirá controlar el momento del eje Y del marco para un tamaño de pantalla de dispositivo específico.

PD: este código no moverá de forma inteligente el marco según la ubicación de TextField.

Crear una extensión para UIDevice

extension UIDevice { enum ScreenType: String { case iPhone4_4S = "iPhone 4 or iPhone 4s" case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE" case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6s, iPhone 7 or iPhone 8" case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6s Plus, iPhone 7 Plus or iPhone 8 Plus" case iPhoneX_Xs = "iPhone X, iPhone Xs" case iPhoneXR = "iPhone XR" case iPhoneXSMax = "iPhone Xs Max" case unknown } var screenType: ScreenType { switch UIScreen.main.nativeBounds.height { case 960: return .iPhone4_4S case 1136: return .iPhones_5_5s_5c_SE case 1334: return .iPhones_6_6s_7_8 case 1920, 2208: return .iPhones_6Plus_6sPlus_7Plus_8Plus case 1792: return .iPhoneXR case 2436: return .iPhoneX_Xs case 2688: return .iPhoneXSMax default: return .unknown } } }

Agregar NotificationObserver en 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)

Selector

@objc func keyboardWillShow(notification: NSNotification) { if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil { if self.view.frame.origin.y == 0 { switch (UIDevice.current.screenType.rawValue) { case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue): self.view.frame.origin.y -= 210 case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue): self.view.frame.origin.y -= 110 case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue): self.view.frame.origin.y -= 80 case (UIDevice.ScreenType.iPhoneX_Xs.rawValue): self.view.frame.origin.y -= 70 case (UIDevice.ScreenType.iPhoneXR.rawValue): self.view.frame.origin.y -= 70 case (UIDevice.ScreenType.iPhoneXSMax.rawValue): self.view.frame.origin.y -= 70 default: self.view.frame.origin.y -= 150 } } } } @objc func keyboardWillHide(notification: NSNotification) { if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil { if self.view.frame.origin.y != 0 { switch (UIDevice.current.screenType.rawValue) { case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue): self.view.frame.origin.y += 210 case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue): self.view.frame.origin.y += 110 case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue): self.view.frame.origin.y += 80 case (UIDevice.ScreenType.iPhoneX_Xs.rawValue): self.view.frame.origin.y += 70 case (UIDevice.ScreenType.iPhoneXR.rawValue): self.view.frame.origin.y += 70 case (UIDevice.ScreenType.iPhoneXSMax.rawValue): self.view.frame.origin.y += 70 default: self.view.frame.origin.y += 150 } } } }


Reescrito para swift 4.2

En ViewDidLoad ..

NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWasShown), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWillBeHidden), name: UIResponder.keyboardWillHideNotification, object: nil)

Funciones restantes

func registerForKeyboardNotifications(){ //Adding notifies on keyboard appearing NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) } func deregisterFromKeyboardNotifications(){ //Removing notifies on keyboard appearing NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) } @objc 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[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 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) } } } @objc func keyboardWillBeHidden(notification: NSNotification){ //Once keyboard disappears, restore original positions var info = notification.userInfo! let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 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 }


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 }


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

Okay . Primero confirme con el protocolo UITextFieldDelegate

class YourClass:UITextFieldDelegate

Luego implemente 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 usar una vista de desplazamiento y colocar la vista que debe desplazarse hacia arriba / abajo dentro de la vista de desplazamiento y manejar los eventos del teclado en consecuencia


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


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 el textView no se manejó cuando estaba cubierto por el teclado. Desafortunadamente, la documentación de Apple no funcionará porque, por cualquier razón, el teclado se llama DESPUÉS de que se llama a 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 AMBAS condiciones existen.

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 de la vista estuviera a la vista. Entonces, el código que escribí en realidad toma el punto Inferior-Izquierdo referenciado en pantalla de cualquier textView o textField y ve si cae en las coordenadas referenciadas en pantalla del teclado presentado, lo que implica que el teclado cubre una parte de él.

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

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

self.automaticallyAdjustsScrollViewInsets = false

Recorre cada textView y textField para establecer delegados 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 en 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() } }


Aquí están mis 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 importe el marco IQKeyboardManagerSwift y habilite IQKeyboardManager.

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

Y eso es todo. ¡Fácil!


Creo que esta cláusula está mal:

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, restore 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 }

Si bien el origen de activeField puede estar por encima del teclado, el maxY podría no ...

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


El que encontré que funcionaba 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.


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

Paso 1:-

Me gusta como var activeTextField: UITextField ?

Paso 2: - Después de esto, agregue 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 }


Simplemente use esta extensión para mover cualquier UIView cuando se presente 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 su vista descarga, vincule su vista al teclado

UiView.bindToKeyboard()


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 esté debajo del teclado. Solo necesita poner los 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, restore 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 delegados correctos en sus métodos de inicialización: por ejemplo:

self.you_text_field.delegate = self

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

Editar / Actualizar: sintaxis Swift 4.2

func registerForKeyboardNotifications(){ //Adding notifies on keyboard appearing NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil) } func deregisterFromKeyboardNotifications(){ //Removing notifies on keyboard appearing NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil) } @objc 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[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 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) } } } @objc func keyboardWillBeHidden(notification: NSNotification){ //Once keyboard disappears, restore original positions var info = notification.userInfo! let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 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 }


Utilizo SwiftLint, que tuvo algunos problemas con el formato de la respuesta aceptada. Específicamente:

sin espacio antes de los dos puntos, sin fuerza de lanzamiento, prefiera UIEdgeInset (arriba: etc ... en lugar de UIEdgeInsetMake.

así que aquí están esas actualizaciones para Swift 3

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


Ya se dan 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 un IBOutlet de las principales restricciones de UIViewcontroller de su UIViewcontroller esta manera: (aquí UIView es la subvista de UIScrollView que significa que debe tener un UIScrollView para todas sus subViews )

@IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint!

Y otra variable 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 pegue 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 delegados a todos sus UITextField s en UIStoryboard

¡Buena suerte!


Swift 4

Puede moverse fácilmente hacia arriba y hacia abajo UITextField con el teclado con animación

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<UITouch>, 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 actualizó mi solución

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

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.2

Mi solución centrará (verticalmente) la vista en UITextField si su posición está debajo del teclado.

Paso 1: Cree un nuevo archivo swift y copie y pegue la UIViewWithKeyboard clase.
Paso 2: en Interface Builder configúrelo como una Clase personalizada para su máximo rendimiento 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 } } }


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 desea; puede agregar condiciones "si" para ciertos campos de texto, pero este tipo funciona para todos ...


Swift 4 (** actualizado ) con extensión **

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

    self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain self.watchForKeyboard()

  4. agregue la siguiente extensión

    import UIKit 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:UIResponder.keyboardWillShowNotification, object: nil); NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name:UIResponder.keyboardWillHideNotification, object: nil); } @objc func keyboardWasShown(notification: NSNotification) { let info = notification.userInfo! let keyboardFrame: CGRect = (info[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue UIView.animate(withDuration: 0.3, animations: { () -> Void in self.containerDependOnKeyboardBottomConstrain.constant = -keyboardFrame.height self.view.layoutIfNeeded() }) } @objc func keyboardWillHide(notification: NSNotification) { UIView.animate(withDuration: 0.3, animations: { () -> Void in self.containerDependOnKeyboardBottomConstrain.constant = 0 self.view.layoutIfNeeded() }) } }