Soy nuevo aquí y estoy empezando con Swift para iOS.

Comencé a crear una aplicación sencilla que hace algunas operaciones. Pero estoy teniendo algunos problemas cuando aparezca el teclado, ocultando uno de mis campos de texto. Creo que es un problema común y se me hizo un poco de investigación, pero no pude encontrar nada que resolver mi problema. Y quiero usar un pergamino en lugar de animar el textField para hacerla visible.

Gracias!!!!!
(lo siento por errores inglés)

14 Comentarios

  1. 112

    En ViewDidLoad, registro de las notificaciones:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillShow), name:UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillHide), name:UIKeyboardWillHideNotification, object: nil)

    Agregar a continuación los métodos de observador que hace el desplazamiento automático cuando aparecerá el teclado.

    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    
    func keyboardWillShow(notification:NSNotification){
    
        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
        keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil)
    
        var contentInset:UIEdgeInsets = self.scrollView.contentInset
        contentInset.bottom = keyboardFrame.size.height
        scrollView.contentInset = contentInset
    }
    
    func keyboardWillHide(notification:NSNotification){
    
        let contentInset:UIEdgeInsets = UIEdgeInsetsZero
        scrollView.contentInset = contentInset
    }

    EDICIÓN: Este post ha sido actualizado para reflejar las mejores prácticas en Swift 2.2 Objetivo C selectores.

    • El uso de estos código, junto con scrollView salvó la vida. Sólo añadir 20 contentInset.parte inferior para desplazarse correctamente. contentInset.abajo = keyboardFrame.tamaño.altura + 20
    • Funciona a la perfección! El contentInset se puede establecer un ‘vamos’ en lugar de ‘var’ en el keyboardWillHide aunque 🙂
    • No trabajo con UITextView dentro de UIView archivo nib.
    • Sí, parece que no funciona con TextView
    • Impresionante , realmente Gracias
    • Esta solución funciona cuando el UIControlView se desplaza.

  2. 65

    La respuesta rápida 3:

    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)

    Y luego:

    func keyboardWillShow(notification:NSNotification){
        //give room at the bottom of the scroll view, so it doesn't cover up anything the user needs to tap
        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)
    
        var contentInset:UIEdgeInsets = self.theScrollView.contentInset
        contentInset.bottom = keyboardFrame.size.height
        theScrollView.contentInset = contentInset
    }
    
    func keyboardWillHide(notification:NSNotification){
        let contentInset:UIEdgeInsets = UIEdgeInsets.zero
        theScrollView.contentInset = contentInset
    }
    • También tal vez mantener el textFieldShouldReturn método anterior, si desea utilizar la tecla de retorno para despedir el teclado. Thx por la actualización!
    • No trabajo con UITextView dentro de UIView archivo nib.
    • No olvides NotificationCenter.default.removeObserver(self)
    • Funciona como un encanto. Gracias Daniel.
    • Apple Docs para NotificationCenter: If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its deallocation method.
    • Creo que usted necesita reemplazar UIKeyboardFrameBeginUserInfoKey con UIKeyboardFrameEndUserInfoKey en su respuesta. Debido a que usted necesita cuadro final en willShow método.
    • La primera vez que el teclado se abre, su altura es cero para mí. Después de que funciona bien, aunque. ¿Sabe usted de cualquier error relacionado con esto?

  3. 25

    Aquí es una solución completa, utilizando la guardia y concisa código. Además de corregir el código en keyboardWillHide sólo a restablecer la bottom a 0.

    @IBOutlet weak var scrollView: UIScrollView!
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        registerNotifications()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        unregisterNotifications()
    }
    
    private func registerNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    private func unregisterNotifications() {
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
        scrollView.contentInset.bottom = 0
    }
    
    @objc private func keyboardWillShow(notification: NSNotification){
        guard let keyboardFrame = notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
        scrollView.contentInset.bottom = view.convert(keyboardFrame.cgRectValue, from: nil).size.height
    }
    
    @objc private func keyboardWillHide(notification: NSNotification){
        scrollView.contentInset.bottom = 0
    }
    • Bonita respuesta. Para ser aún más concisa que se puede decir «.UIKeyboardWillShow» en lugar de «NSNotification.Nombre.UIKeyboardWillShow». He actualizado su respuesta, si no te importa.
    • UIKeyboardFrameBeginUserInfoKey es la clave equivocada; debe ser UIKeyboardFrameEndUserInfoKey (comenzar → final). Esta solución ofrece a cero de la altura para el teclado.
    • Esto me Ayudó! Gracias Compañero 🙂
    • Gran respuesta. Creo que sería más seguro para el uso viewDidDisappear() – si la vista es desplazado de distancia, mientras que el teclado es visible es concebible puede quitar la notificación de observador ante el ocultar que en realidad ha tenido lugar, y por lo tanto no se restablece su contenido en el recuadro. Para estar más seguro también me gustaría establecer el margen de 0 cuando la notificación observador es eliminado.
    • Bastante limpio solución. Además, keyboardWillShow y keyboardWillHide puede ser privado.
    • Gracias @Richard. He actualizado mi respuesta en consecuencia.
    • Gracias @Leo. He actualizado mi respuesta en consecuencia.

  4. 12

    para Swift 4.0

    En ViewDidLoad

    //setup keyboard event
    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)

    Agregar a continuación los métodos de observador que hace el desplazamiento automático cuando aparecerá el teclado.

    @objc func keyboardWillShow(notification:NSNotification){
        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)
    
        var contentInset:UIEdgeInsets = self.ui_scrollView.contentInset
        contentInset.bottom = keyboardFrame.size.height
        ui_scrollView.contentInset = contentInset
    }
    
    @objc func keyboardWillHide(notification:NSNotification){
    
        let contentInset:UIEdgeInsets = UIEdgeInsets.zero
        ui_scrollView.contentInset = contentInset
    }
  5. 8

    contentInset no funciona para mí, porque quiero que el scrollview mover todo el camino hasta la parte superior del teclado. Así que yo uso contentOffset:

    func keyboardWillShow(notification:NSNotification) {
        guard let keyboardFrameValue = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue else {
            return
        }
        let keyboardFrame = view.convert(keyboardFrameValue.cgRectValue, from: nil)
        scrollView.contentOffset = CGPoint(x:0, y:keyboardFrame.size.height)
    }
    
    func keyboardWillHide(notification:NSNotification) {
        scrollView.contentOffset = .zero
    }
    • Este fue el que en realidad trabajaba para mí!
  6. 6

    De la respuesta por Sudheer Palchuri, convertido para Swift 4.

    En ViewDidLoad, registro de las notificaciones:

    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)

    Y luego:

    //MARK: - Keyboard Delegates
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    
    @objc func keyboardWillShow(notification:NSNotification){
    
        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)
    
        var contentInset:UIEdgeInsets = self.scrollView.contentInset
        contentInset.bottom = keyboardFrame.size.height
        self.scrollView.contentInset = contentInset
    }
    
    @objc func keyboardWillHide(notification:NSNotification){
    
        let contentInset:UIEdgeInsets = UIEdgeInsets.zero
        self.scrollView.contentInset = contentInset
    }
  7. 4

    La lectura de los enlaces que me envió, he encontrado una manera de hacer que funcione, gracias!:

    func textFieldDidBeginEditing(textField: UITextField) {            
        if (textField == //your_field) {
            scrollView.setContentOffset(CGPointMake(0, field_extra.center.y-280), animated: true)
            callAnimation()
            viewDidLayoutSubviews()
        }
    }
    
    func textFieldDidEndEditing(textField: UITextField) {    
        if (textField == //your_field){
            scrollView .setContentOffset(CGPointMake(0, 0), animated: true)
            viewDidLayoutSubviews()
        }
    }
  8. 4

    Swift 5 Solo ajustar el ScrollView cuando TextField se oculta por el teclado (para varios campos de texto)

    Agregar /Quitar Observadores:

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

    Seguir la pista de estos valores, por lo que puede volver a su posición original:

    var scrollOffset : CGFloat = 0
    var distance : CGFloat = 0

    Ajustar ScrollView contentOffset dependiendo de TextField Ubicación:

    @objc func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    
            var safeArea = self.view.frame
            safeArea.size.height += scrollView.contentOffset.y
            safeArea.size.height -= keyboardSize.height + (UIScreen.main.bounds.height*0.04) //Adjust buffer to your liking
    
            //determine which UIView was selected and if it is covered by keyboard
    
            let activeField: UIView? = [textFieldA, textViewB, textFieldC].first { $0.isFirstResponder }
            if let activeField = activeField {
                if safeArea.contains(CGPoint(x: 0, y: activeField.frame.maxY)) {
                    print("No need to Scroll")
                    return
                } else {
                    distance = activeField.frame.maxY - safeArea.size.height
                    scrollOffset = scrollView.contentOffset.y
                    self.scrollView.setContentOffset(CGPoint(x: 0, y: scrollOffset + distance), animated: true)
                }
            }
            //prevent scrolling while typing
    
            scrollView.isScrollEnabled = false
        }
    }
    @objc func keyboardWillHide(notification: NSNotification) {
            if distance == 0 {
                return
            }
            //return to origin scrollOffset
            self.scrollView.setContentOffset(CGPoint(x: 0, y: scrollOffset), animated: true)
            scrollOffset = 0
            distance = 0
            scrollView.isScrollEnabled = true
    }

    Asegúrese de utilizar [UIResponder.keyboardFrameEndUserInfoKey] para obtener la correcta altura del teclado la primera vez.

  9. 2

    Usted puede animar a su scrollview al centro en su UITextField en el teclado apariencia (es decir. hacer de su textfield la primera respuesta) a través de un desplazamiento desplazamiento. Aquí hay un par de buenos recursos para empezar (hay un montón en este sitio):

    Cómo mover mediante programación un UIScrollView para centrarse en un control por encima del teclado?

    Cómo hacer un UIScrollView desplazamiento automático cuando un UITextField se convierte en un primer respondedor

    Además, si usted sólo tiene que utilizar un UITableView con su contenido en las células, cuando el campo de texto se convierte en el primer respondedor, el UITableViewController se desplazará automáticamente el campo de texto de una celda para usted (aunque no estoy seguro de que es lo que quieres hacer).

  10. 2

    Una respuesta rápida 3, basado en el propuesto por Daniel Jones, pero más seguro (gracias a la guardia), más concisa y con el consecuente desplazamiento del indicador de márgenes:

    @objc private func keyboardWillBeShown(notification: NSNotification) {
        guard let keyboardFrameValue = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue else { return }
        let keyboardFrame = view.convert(keyboardFrameValue.cgRectValue, from: nil)
        scrollView.contentInset.bottom = keyboardFrame.size.height
        scrollView.scrollIndicatorInsets = scrollView.contentInset
    }
    
    @objc private func keyboardWillBeHidden() {
        scrollView.contentInset = .zero
        scrollView.scrollIndicatorInsets = scrollView.contentInset
    }
    • Puedo obtener ViewController no tiene ningún miembro de self.scrollView
    • Eso es porque usted necesita para crear IBOutlet para su scrollview
  11. 1

    En Swift4, sólo tiene que añadir la siguiente extensión.

    extension UIViewController {
    
       func setupViewResizerOnKeyboardShown() {
            NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.keyboardWillShowForResizing),
                                               name: 
            Notification.Name.UIKeyboardWillShow,
                                               object: nil)
            NotificationCenter.default.addObserver(self,
                                               selector: #selector(self.keyboardWillHideForResizing),
                                               name: Notification.Name.UIKeyboardWillHide,
                                               object: nil)
            }
    
       @objc func keyboardWillShowForResizing(notification: Notification) {
            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
            let window = self.view.window?.frame {
            //We're not just minusing the kb height from the view height because
            //the view could already have been resized for the keyboard before
            self.view.frame = CGRect(x: self.view.frame.origin.x,
                                     y: self.view.frame.origin.y,
                                     width: self.view.frame.width,
                                     height: window.origin.y + window.height - keyboardSize.height)
          } else {
            debugPrint("We're showing the keyboard and either the keyboard size or window is nil: panic widely.")
          }
      }
    
       @objc func keyboardWillHideForResizing(notification: Notification) {
         if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            let viewHeight = self.view.frame.height
            self.view.frame = CGRect(x: self.view.frame.origin.x,
                                     y: self.view.frame.origin.y,
                                     width: self.view.frame.width,
                                     height: viewHeight + keyboardSize.height)
        } else {
            debugPrint("We're about to hide the keyboard and the keyboard size is nil. Now is the rapture.")
        }
       }
     }
  12. 0
    override func viewDidLoad() {
        super.viewDidLoad()
        //Do any additional setup after loading the view, typically from a nib.
    
        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)
    
    }
    
    func keyboardWillShow(_ notification:Notification) {
    
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
        }
    }
    func keyboardWillHide(_ notification:Notification) {
    
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
        }
    }
  13. 0

    En caso de que alguien está buscando el código Objective-C para esta solución:

    - (void)keyboardWasShown:(NSNotification *)notification {
            NSDictionary* info = [notification userInfo];
            CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
            UIEdgeInsets contentInsets = baseScrollView.contentInset;
            contentInsets.bottom = kbSize.height;
            baseScrollView.contentInset = contentInsets;
        }
    
        - (void)keyboardWillBeHidden:(NSNotification *)notification {
            UIEdgeInsets contentInsets = UIEdgeInsetsZero;
            baseScrollView.contentInset = contentInsets;
            [baseScrollView endEditing:YES];
        }
  14. 0

    En mi situación era

    ScrollView
    –>
    Formato tableview
    –>
    TableViewCell

    Así que tuve que hacer y posición en relación a teclado marco y comprobar si el teclado y la posición y mi campo activo de posición y se intersectan o no

       @objc func keyboardWillShow(_ notification: Foundation.Notification) {
    
            var userInfo = notification.userInfo!
            var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
            keyboardFrame = self.view.convert(keyboardFrame, from: nil)
    
            var contentInset:UIEdgeInsets = self.scrollView!.contentInset
            contentInset.bottom = keyboardFrame.size.height
            let loc = self.activeTextField?.convert(activeTextField!.bounds, to: self.view)
    
            if keyboardFrame.origin.y <  loc!.origin.y {
                self.scrollView?.contentOffset = CGPoint.init(x: (self.scrollView?.contentOffset.x)!, y: loc!.origin.y)
            }
    
            if self.scrollView?.contentInset.bottom == 0 {
                self.scrollView?.contentInset = contentInset
            }
    
        }

Dejar respuesta

Please enter your comment!
Please enter your name here