ios swift uitextfield

text field ios 11



UITextField, el texto salta ligeramente cuando comienza la ediciĆ³n (4)

Estoy teniendo un problema extraño aquí. Tengo UITextFields en las celdas de mi tabla. Cuando selecciono el campo, el texto salta ligeramente hacia abajo:

La fuente es la predeterminada del sistema 17. Me he adjust to fit en el tamaño 17. He intentado desactivar el adjust to fit y todavía hay un salto. He intentado usar diferentes estilos de borde y esto tampoco hace ninguna diferencia. He intentado apagar el clip a los límites, todavía salta. También he intentado hacer el cuadro más alto (mucho más alto) y todavía salta. Lo único que funciona es si hago el tamaño de fuente mucho más pequeño, por ejemplo, 13. ¿Qué estoy haciendo mal aquí? Si puedo hacer que la fuente sea más pequeña para corregir el salto, ¿por qué no hace que el marco sea más grande? Cualquier sugerencia sobre esto sería realmente apreciada. ¡Gracias!


Así que puedes haberte topado con algo muy extraño. Si subclasifica su UITextField a algo como esto.

class NonJumpyTextField: UITextField { override func textRect(forBounds bounds: CGRect) -> CGRect { var previousRect = super.textRect(forBounds: bounds) print("Bounds: /(bounds)") print("TextRect: /(previousRect)") print("TextFieldRect /(frame)") //not reccomended but does seem to help previousRect.origin.y = 2.25 return previousRect } }

y lea los registros que obtiene algún comportamiento extraño al editarlo imprime

Bounds: (0.0, 0.0, 100.0, 100.0) TextRect: (7.0, 2.0, 86.0, 96.0) TextFieldRect (64.0, 66.0, 97.0, 30.0) Bounds: (0.0, 0.0, 97.0, 30.0) TextRect: (7.0, 2.0, 83.0, 26.0) TextFieldRect (64.0, 66.0, 97.0, 30.0) Bounds: (0.0, 0.0, 100.0, 100.0) TextRect: (7.0, 2.0, 86.0, 96.0) TextFieldRect (64.0, 66.0, 97.0, 30.0)

cuando termine de editar

Bounds: (0.0, 0.0, 97.0, 30.0) TextRect: (7.0, 2.0, 83.0, 26.0) TextFieldRect (64.0, 66.0, 97.0, 30.0) Bounds: (0.0, 0.0, 100.0, 100.0) TextRect: (7.0, 2.0, 86.0, 96.0) TextFieldRect (64.0, 66.0, 97.0, 30.0)

En la muestra en la que estaba trabajando con Brute forzando la posición y, sí ayudé, pero no lo recomendé realmente. Sospecho que el problema tiene que ver con que los límites sean aparentemente aleatorios 100 x 100. Esperemos que algo aquí le ayude a encontrar una solución que funcione para usted.


Cambiar la propiedad contentVerticalAlignment de UITextField puede llevar a este comportamiento extraño.

Puedes añadir un punto de ruptura simbólico.

[UITextField setContentVerticalAlignment:]

a la comprobación si cambia la propiedad contentVerticalAlignment de UITextField accidentalmente.


Debo admitir que siempre he visto este pequeño rebote durante mis desarrollos, pero nunca investigo sobre eso. Algunos puntos que he usado para replicar su problema:

  1. Dos campos de texto con dimensiones y configuraciones predeterminadas.
  2. usando la fuente predeterminada del sistema y cambie su tamaño de 13 a 25 solo para probar el comportamiento

Supongo que hay más formas de resolver tu problema, pero no encuentro una propiedad rápida para detener este pequeño "salto" de texto. He decidido analizar el actual UITextField ( $ xcrun swift -version = Swift 3.1 ) para ver su composición:

import UIKit class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet weak var myTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() myTextField.delegate = self } func textFieldDidBeginEditing(_ textField: UITextField) { print("/ntextFieldDidBeginEditing") showLayersDescription() } func textFieldDidEndEditing(_ textField: UITextField) { print("/ntextFieldDidEndEditing") showLayersDescription() } func showLayersDescription() { myTextField.layer.sublayers?.forEach{ print($0.debugDescription)} } }

donde myTextField es esencialmente uno de los dos campos de texto

Salida utilizando el tamaño de fuente 17 :

Esencialmente parece que hay 3 CALayer :

  • una capa con marco = CGRect (0 0; 252 30) que tiene _UITextFieldRoundedRectBackgroundViewNeue como delegado que tiene la misma dimensión de nuestro campo de texto
  • una capa con marco = CGRect (7 2; 238 26) que solo se muestra en nuestra textFieldDidBeginEditing y tiene un UIFieldEditor como delegado que parece ser el responsable de la parte de edición.
  • una capa que aparece solo en textFieldDidEndEditing con frame = CGRect.zero y con el delegado UITextFieldLabel

Si escribo algo en el primer campo de texto, voy al siguiente campo de texto, no pasa nada, PERO si vuelvo al primer campo de texto y luego al segundo, la capa con marco igual a CGRect.zero cambia a cuadro = CGRect(7 0.5; 238 27.5)

Esta es la pequeña altura (0.5) que podemos ver durante el comienzo y el final de nuestra edición.

Podemos intentar refinar la depuración e interceptar estas capas con una extensión:

extension UITextField { func debugLayers() { print("We have the follow layers:") let FieldEditor: AnyObject.Type = NSClassFromString("UIFieldEditor")! let LabelLayer: AnyObject.Type = NSClassFromString("_UILabelLayer")! let TextFieldRoundRect: AnyObject.Type = NSClassFromString("_UITextFieldRoundedRectBackgroundViewNeue")! self.layer.sublayers?.forEach{ if ($0.delegate?.self.isKind(of: TextFieldRoundRect))! { print("- layer with _UITextFieldRoundedRectBackgroundViewNeue as delegate have frame:/($0.frame)") } if ($0.delegate?.self.isKind(of: FieldEditor))! { print("- layer with UIFieldEditor as delegate have frame:/($0.frame)") } if $0.self.isKind(of: LabelLayer) { print("- layer is kind of _UILabelLayer have frame:/($0.frame)") } } } }

Así que tenemos por ejemplo:

import UIKit class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet weak var myTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() myTextField.delegate = self } func textFieldDidBeginEditing(_ textField: UITextField) { print("/ntextFieldDidBeginEditing") myTextField.debugLayers() } func textFieldDidEndEditing(_ textField: UITextField) { print("/ntextFieldDidEndEditing") myTextField.debugLayers() } }

Salida siempre con tamaño de fuente 17:

Como podemos ver, siempre tenemos esta diferencia de 0.5 en altura en esa capa.

Haciendo otros intentos, he visto que este comportamiento ocurrió solo si el tamaño predeterminado es entre 13 y 17 , menores de 13 años y de 18 a 25, esto no sucedió, ha informado a su pregunta.

Una solución:

Creo que la mejor manera de interceptar y tratar de corregir esta es hacer una nueva extensión:

extension UITextField { override open func layoutSubviews() { super.layoutSubviews() let FieldEditor: AnyObject.Type = NSClassFromString("UIFieldEditor")! let LabelLayer: AnyObject.Type = NSClassFromString("_UILabelLayer")! self.layer.sublayers?.forEach{ if ($0.delegate?.self.isKind(of: FieldEditor))! { var f = $0.frame f.origin.y = 0.0 $0.frame = f } if $0.self.isKind(of: LabelLayer) { var layerFrame = CGRect.zero layerFrame.origin = self.editingRect(forBounds: self.bounds).origin layerFrame.size = self.editingRect(forBounds: self.bounds).size if let size = self.font?.pointSize, 14 ... 17 ~= size { layerFrame.origin.y = -0.5 } else { layerFrame.origin.y = 0.0 } $0.frame = layerFrame } } } }

Consideraciones finales:

Esta extensión suprime el pequeño "salto hacia abajo" del texto durante el cambio a otro campo de texto. Esto es probablemente para equilibrar el:

contentsCenter = CGRect (0.485 0.485; 0.000588235 0.000588235)

que tanto la segunda como la tercera capa tienen con este grupo de tamaños de fuente. Como se ve en la extensión, también puse a cero el origen de altura de la capa con el delegado UIFieldEditor (que antes tiene 2.0 como altura) porque está involucrado en este cambio, lo he hecho para equilibrar las diferencias de restricciones.

Actualización para una extensión válida y aprobada:

He leído su comentario, así que he analizado en profundidad la situación de las capas: lo que he encontrado es que la capa que tiene la brecha de -0.5 altura NUNCA presenta subcapas, cuando la otra SIEMPRE presenta una subcapa (tenga UIFieldEditor como delegado) para que podamos corregir fácilmente la extensión como:

extension UITextField { override open func layoutSubviews() { super.layoutSubviews() self.layer.sublayers?.forEach{ if let subs = $0.sublayers, subs.count>0 { var f = $0.frame f.origin.y = 0.0 $0.frame = f } else { var layerFrame = CGRect.zero layerFrame.origin = self.editingRect(forBounds: self.bounds).origin layerFrame.size = self.editingRect(forBounds: self.bounds).size if let size = self.font?.pointSize, 14 ... 17 ~= size { layerFrame.origin.y = -0.5 } else { layerFrame.origin.y = 0.0 } $0.frame = layerFrame } } } }

He probado esta nueva extensión y se comporta correctamente como la anterior.


Puede intentar aumentar la altura de inputView en UITextField.

UITextField tiene inputView que se presentará cuando el objeto se convierta en el primer respondedor.