fields ios iphone cocoa-touch uikit uitextview

fields - text field ios 11



¿Cómo perder margen/relleno en UITextView? (19)

Tengo una UITextView en mi aplicación iOS, que muestra una gran cantidad de texto. A continuación, estoy paginando este texto utilizando el parámetro de margen de desplazamiento de la UITextView . Mi problema es que el relleno del UITextView confunde mis cálculos, ya que parece ser diferente según el tamaño de fuente y el tipo de letra que uso.

Por lo tanto, planteo la pregunta: ¿Es posible eliminar el relleno que rodea el contenido de la UITextView ?

Esperamos escuchar sus respuestas!


Para 2018

Es uno de los errores más tontos en iOS.

La clase UITextViewFixed es generalmente una solución razonable.

Aquí está la clase:

@IBDesignable class UITextViewFixed: UITextView { override func layoutSubviews() { super.layoutSubviews() setup() } func setup() { textContainerInset = UIEdgeInsets.zero textContainer.lineFragmentPadding = 0 } }

¡No olvide apagar scrollEnabled en el Inspector!

  1. La solución funciona correctamente en el guión gráfico.

  2. La solución funciona correctamente en tiempo de ejecución

Eso es todo, ya está hecho.

En general, eso debería ser todo lo que necesita en la mayoría de los casos .

Incluso si está cambiando la altura de la vista de texto sobre la marcha, esto generalmente hace todo lo que necesita.

(Un ejemplo común de cambio de altura sobre la marcha, es cambiarlo según el tipo de usuario).

Aquí está el UITextView roto de Apple ...

Aquí está UITextViewFixed :

Tenga en cuenta que por supuesto usted debe

apagar scrollEnabled en el inspector!

No te olvides de apagar scrollEnabled! :)

Algunos problemas adicionales

(1) En algunos casos inusuales, por ejemplo, algunos casos de vistas de tabla de altura de celda flexible con altura que cambia dinámicamente, Apple hace la cosa más molesta del mundo: agrega espacio adicional en la parte inferior . ¡No realmente! Esta tendría que ser una de las cosas más molestas en iOS.

Aquí hay una "solución rápida" para agregar que a menudo ayuda con esa locura.

... textContainerInset = UIEdgeInsets.zero textContainer.lineFragmentPadding = 0 // this is not ideal, but you can sometimes use this // to fix the "space at bottom" insanity var b = bounds let h = sizeThatFits(CGSize( width: bounds.size.width, height: CGFloat.greatestFiniteMagnitude) ).height b.size.height = h bounds = b ...

(2) A veces, para arreglar otro problema sutil de Apple, debes agregar esto:

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) { super.setContentOffset(contentOffset, animated: false) }

(3) Podría decirse que deberíamos agregar:

contentInset = UIEdgeInsets.zero

justo después de .lineFragmentPadding = 0 en UITextViewFixed . Sin embargo ... simplemente no funciona en iOS actual! Puede ser necesario agregar eso en el futuro.

El hecho de que UITextView esté totalmente roto en iOS es una de las cosas más extrañas de toda la computación móvil.

Finalmente, aquí hay una sugerencia algo similar para el campo de texto: https://.com/a/43099816/294884


Último Swift

self.textView.textContainerInset = .init (arriba: -2, izquierda: 0, abajo: 0, derecha: 0) self.textView.textContainer.lineFragmentPadding = 0


A partir de algunas de las buenas respuestas que ya se dieron, aquí se encuentra una solución basada exclusivamente en Interface Builder que utiliza los atributos de tiempo de ejecución definidos por el usuario y funciona en iOS 7.0+:


Aquí hay una pequeña extensión fácil que eliminará el margen predeterminado de Apple de cada vista de texto en su aplicación.

Nota: Interface Builder seguirá mostrando el margen anterior, pero su aplicación funcionará como se esperaba.

extension UITextView { open override func awakeFromNib() { super.awakeFromNib(); removeMargins(); } /** Removes the Apple textview margins. */ public func removeMargins() { self.contentInset = UIEdgeInsetsMake( 0, -textContainer.lineFragmentPadding, 0, -textContainer.lineFragmentPadding); } }


Aquí hay una versión actualizada de la respuesta muy útil de Fattie. Agrega 2 líneas muy importantes que me ayudaron a obtener un diseño perfecto para iOS 10 y 11 (y probablemente también para las más bajas).
re

@IBDesignable class UITextViewFixed: UITextView { override func layoutSubviews() { super.layoutSubviews() setup() } func setup() { translatesAutoresizingMaskIntoConstraints = true textContainerInset = UIEdgeInsets.zero textContainer.lineFragmentPadding = 0 translatesAutoresizingMaskIntoConstraints = false } }

¡Las líneas importantes son las dos declaraciones translatesAutoresizingMaskIntoConstraints = <true/false> !

¡Esto elimina sorprendentemente todos los márgenes en todas mis circunstancias!

Si bien textView no es el primer respondedor, puede suceder que haya un margen inferior extraño que no se pueda resolver con el método sizeThatFits que se menciona en la respuesta aceptada.
Al tocar el textView, de repente, el extraño margen inferior desapareció y todo parecía que debía, pero solo en cuanto el textView tiene el primer firstResponder .

Así que leí aquí en SO que habilitar y deshabilitar translatesAutoresizingMaskIntoConstraints ayuda al configurar el marco / límites manualmente entre las llamadas.

Afortunadamente, esto no solo funciona con la configuración del marco, sino también con las 2 líneas de setup() intercaladas entre las dos translatesAutoresizingMaskIntoConstraints .

Esto, por ejemplo, es muy útil cuando se calcula el marco de una vista utilizando systemLayoutSizeFitting en una UIView . Devuelve el tamaño correcto (que anteriormente no lo hacía)!

Como en la respuesta original mencionada:
¡No olvide apagar scrollEnabled en el Inspector!
Esa solución funciona correctamente en el guión gráfico, así como en el tiempo de ejecución.

Eso es todo, ¡ya está hecho!


El desplazamiento textView también afecta la posición del texto y hace que se vea como no centrado verticalmente. Logré centrar el texto en la vista deshabilitando el desplazamiento y configurando el recuadro superior en 0:

textView.scrollEnabled = NO; textView.textContainerInset = UIEdgeInsetsMake(0, textView.textContainerInset.left, textView.textContainerInset.bottom, textView.textContainerInset.right);

Por alguna razón aún no lo he descubierto, el cursor aún no está centrado antes de que comience la escritura, pero el texto se centra inmediatamente cuando comienzo a escribir.


En iOS 5 UIEdgeInsetsMake(-8,-8,-8,-8); Parece funcionar muy bien.


Haciendo la solución de inserción todavía tenía relleno en el lado derecho y en la parte inferior. También la alineación del texto estaba causando problemas. La única manera segura que encontré fue colocar la vista de texto dentro de otra vista que está recortada a límites.


He encontrado un enfoque más, obteniendo la vista con el texto de las subvistas de UITextView y configurándolo en el método layoutSubview de una subclase:

- (void)layoutSubviews { [super layoutSubviews]; const int textViewIndex = 1; UIView *textView = [self.subviews objectAtIndex:textViewIndex]; textView.frame = CGRectMake( kStatusViewContentOffset, 0.0f, self.bounds.size.width - (2.0f * kStatusViewContentOffset), self.bounds.size.height - kStatusViewContentOffset); }


Para iOS 10, la siguiente línea funciona para la eliminación del relleno superior e inferior.

captionTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)


Para iOS 7.0, he encontrado que el truco contentInset ya no funciona. Este es el código que usé para deshacerme del margen / relleno en iOS 7.

Esto lleva el borde izquierdo del texto al borde izquierdo del contenedor:

textView.textContainer.lineFragmentPadding = 0

Esto hace que la parte superior del texto se alinee con la parte superior del contenedor

textView.textContainerInset = .zero

Ambas líneas son necesarias para eliminar completamente el margen / relleno.


Para mí (iOS 11 y Xcode 9.4.1), lo que funcionó mágicamente fue la configuración de la propiedad textView.font para el estilo UIFont.preferred(forTextStyle:UIFontTextStyle) y también la primera respuesta como lo menciona @Fattie. Pero la respuesta de @Fattie no funcionó hasta que configuré la propiedad textView.font, de lo contrario, UITextView sigue comportándose de forma errática.


Puedes usar la propiedad UITextView de UITextView :

textView.textContainerInset = UIEdgeInsetsMake (10, 10, 10, 10);

(arriba a la izquierda, abajo a la derecha)


Storyboard o solución Interface Builder, utilizando atributos de tiempo de ejecución definidos por el usuario. Actualizar. Se agregaron capturas de pantalla de iOS7.1 y iOS6.1 con contentInset = {{-10, -5}, {0, 0}}


Todas estas respuestas abordan la pregunta del título, pero quería proponer algunas soluciones para los problemas presentados en el cuerpo de la pregunta del OP.

Tamaño del contenido del texto

Una forma rápida de calcular el tamaño del texto dentro de UITextView es usar NSLayoutManager :

UITextView *textView; CGSize textSize = [textView usedRectForTextContainer:textView.textContainer].size;

Esto proporciona el contenido total desplazable, que puede ser más grande que el UITextView la UITextView . Descubrí que esto es mucho más preciso que textView.contentSize ya que en realidad calcula la cantidad de espacio que ocupa el texto. Por ejemplo, dado un UITextView vacío:

textView.frame.size = (width=246, height=50) textSize = (width=10, height=16.701999999999998) textView.contentSize = (width=246, height=33) textView.textContainerInset = (top=8, left=0, bottom=8, right=0)

Altura de la línea

UIFont tiene una propiedad que le permite obtener rápidamente la altura de línea para la fuente dada. Para que pueda encontrar rápidamente la altura de línea del texto en su UITextView con:

UITextView *textView; CGFloat lineHeight = textView.font.lineHeight;

Cálculo del tamaño del texto visible

Determinar la cantidad de texto que es realmente visible es importante para manejar un efecto de "paginación". UITextView tiene una propiedad llamada textContainerInset que en realidad es un margen entre el actual UITextView.frame y el texto en sí. Para calcular la altura real del marco visible puede realizar los siguientes cálculos:

UITextView *textView; CGFloat textViewHeight = textView.frame.size.height; UIEdgeInsets textInsets = textView.textContainerInset; CGFloat textHeight = textViewHeight - textInsets.top - textInsets.bottom;

Determinar el tamaño de paginación

Finalmente, ahora que tiene el tamaño del texto visible y el contenido, puede determinar rápidamente cuáles deberían ser sus compensaciones restando el textHeight del textSize :

// where n is the page number you want CGFloat pageOffsetY = textSize - textHeight * (n - 1); textView.contentOffset = CGPointMake(textView.contentOffset.x, pageOffsetY); // examples CGFloat page1Offset = 0; CGFloat page2Offset = textSize - textHeight CGFloat page3Offset = textSize - textHeight * 2

Usando todos estos métodos, no toqué mis recuadros y pude ir al caret o a cualquier parte del texto que quiero.


Definitivamente evitaría cualquier respuesta que involucre valores codificados, ya que los márgenes reales pueden cambiar con la configuración de tamaño de fuente del usuario, etc.

Aquí está la respuesta de @ user1687195, escrita sin modificar el textContainer.lineFragmentPadding (porque la docs indica que este no es el uso previsto).

Esto funciona muy bien para iOS 7 y versiones posteriores.

self.textView.textContainerInset = UIEdgeInsetsMake( 0, -self.textView.textContainer.lineFragmentPadding, 0, -self.textView.textContainer.lineFragmentPadding);

Este es efectivamente el mismo resultado, solo un poco más limpio, ya que no hace mal uso de la propiedad lineFragmentPadding.


Esta solución se escribió en 2009 cuando se lanzó iOS 3.0. Ya no se aplica.

Me encontré con el mismo problema, al final tuve que terminar usando

nameField.contentInset = UIEdgeInsetsMake(-4,-8,0,0);

donde nameField es un UITextView . La fuente que estaba usando era Helvetica 16 puntos. Es solo una solución personalizada para el tamaño de campo particular que estaba dibujando. Esto hace que el offset izquierdo quede al ras con el lado izquierdo, y el offset superior donde lo quiero para el cuadro en el que se dibuja.

Además, parece que esto solo se aplica a UITextViews en las que está usando la alineación predeterminada, es decir.

nameField.textAlignment = NSTextAlignmentLeft;

Alinear a la derecha, por ejemplo, y el UIEdgeInsetsMake parece no tener ningún impacto en el borde derecho en absoluto.

Como mínimo, el uso de la propiedad .contentInset le permite colocar sus campos con las posiciones "correctas", y acomodar las desviaciones sin compensar sus UITextViews .


Para swift 4, Xcode 9

Utilice la siguiente función para cambiar el margen / relleno del texto en UITextView

función pública UIEdgeInsetsMake (_ parte superior: CGFloat, _ izquierda: CGFloat, _ parte inferior: CGFloat, _ derecha: CGFloat) -> UIEdgeInsets

así que en este caso es

self.textView?.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)


[firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];