¿Cómo perder margen / relleno en UITextView?

Tengo un UITextView en mi aplicación iOS, que muestra una gran cantidad de text. Luego estoy pagando este text utilizando el parámetro de margen de compensación de UITextView . Mi problema es que el relleno de UITextView está confundiendo 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 UITextView ?

¡Espero escuchar tus respuestas!

Para 2017

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

UITextViewFixed es generalmente una solución razonable:

 @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!

Esto funciona correctamente en storyboard , ya que está trabajando en Xcode.

Eso es todo, ya está.

En general, eso debería ser todo lo que necesita en la mayoría de los casos , incluso cuando cambia la altura de la vista de text sobre la marcha, por ejemplo, cuando el usuario escribe.

ITUextView inutilizable de Apple …

captura de pantalla de IB con UITextView

UITextViewFixed en casi todos los casos es una solución aceptable:

captura de pantalla de IB con UITextViewFixed

(Se agregó amarillo para mayor claridad.) Tenga en count que, por supuesto, debe

Desactiva scrollEnabled en el Inspector.

¡No olvides apagar scrollEnabled!


¡Y además! … ese problema del "espacio inferior"

En algunos casos, tal vez particularmente cuando se utiliza la reproducción automática con vistas flexibles de la tabla de altura de celda, que cambian a medida que avanza, Apple es la cosa más exasperante del mundo,

agregan espacio adicional en la parte inferior.

Tendría que ser una de las cosas más exasperantes de iOS.

Aquí hay una "solución rápida" para esa locura.

 @IBDesignable class UITextViewFixedWithKludge: UITextView { override func layoutSubviews() { super.layoutSubviews() setup() } func setup() { 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 } } 

Notas:

(1) A veces, para solucionar otro desorder sutil de Apple, debes agregar esto:

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

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

 contentInset = UIEdgeInsets.zero 

(haz eso justo después de textContainer.lineFragmentPadding = 0 ) ¡Sin embargo … no funciona en iOS actual! Puede ser necesario agregar eso en futuras versiones del SO.

El hecho de que UITextView , de todas las cosas, esté totalmente roto en iOS es solo una de las cosas más extrañas en toda la informática mobile.

Finalmente, aquí hay un consejo algo similar para el campo de text: https://stackoverflow.com/a/43099816/294884

Para iOS 7.0, descubrí que el truco de contenido de inicio ya no funciona. Este es el código que solía eliminar del margen / relleno en iOS 7.

Esto trae el borde izquierdo del text al borde izquierdo del contenedor:

 self.textView.textContainer.lineFragmentPadding = 0 

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

 self.textView.textContainerInset = .zero 

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

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 una 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 desplazamiento hacia la izquierda se alinee con el lado izquierdo, y el desplazamiento superior donde lo quiero para el cuadro se dibuja.

Además, esto solo parece aplicarse a UITextViews donde está utilizando el aligment pnetworkingeterminado, es decir.

 nameField.textAlignment = NSTextAlignmentLeft; 

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

Al less, usar la propiedad .contentInset le permite ubicar sus campos con las posiciones "correctas" y acomodar las desviaciones sin compensar sus UITextViews .

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

Desarrollando algunas de las buenas respuestas ya dadas, aquí hay una solución puramente basada en Interface Builder que hace uso de Atributos de Runtime definidos por el usuario y funciona en iOS 7.0+:

introduzca la descripción de la imagen aquí

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

Aquí está la respuesta de @ user1687195, escrita sin modificar textContainer.lineFragmentPadding (porque el estado de los documentos 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); 

Esto es efectivamente el mismo resultado, solo un poco más limpio, ya que no utiliza mal la propiedad lineFragmentPadding.

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 text

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

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

Esto proporciona el contenido total desplazable, que puede ser mayor que el marco de UITextView . Encontré que esto es mucho más preciso que textView.contentSize ya que realmente calcula cuánto espacio ocupa el text. 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 rápidamente le permite get la altura de línea para la fuente dada. Para que pueda encontrar rápidamente la altura de línea del text en su UITextView con:

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

Cálculo del tamaño del text visible

La determinación de la cantidad de text que es realmente visible es importante para manejar un efecto de "búsqueda". UITextView tiene una propiedad llamada textContainerInset que en realidad es un margen entre el UITextView.frame real y el text 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; 

Determinación del tamaño de búsqueda

Por último, ahora que tiene el tamaño del text visible y el contenido, puede determinar rápidamente cuáles deberían ser sus desplazamientos restando textHeight del textHeight de 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 methods, no toqué mis recuadros y pude ir al cursor o donde sea que quiera en el text.

Storyboard o Interface Builder, utilizando los attributes de time de ejecución definidos por el usuario. Actualizar. Se agregaron capturas de pantalla de iOS7.1 e iOS6.1 con contentInset = {{-10, -5}, {0, 0}} introduzca la descripción de la imagen aquíintroduzca la descripción de la imagen aquí

puede usar la propiedad UITextView de UITextView :

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

(arriba a la izquierda, abajo a la derecha)

Para iOS 10, la siguiente línea funciona para eliminar el relleno superior e inferior.

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

Tenga en count que cambiarlo a UIEdgeInset.zero en el lado derecho no funciona

Haciendo la solución de inserción todavía tenía relleno en el lado derecho y el background. También la alignment del text causaba problemas. La única manera segura que encontré fue poner la vista de text dentro de otra vista que está recortada a límites.

El desplazamiento de textView también afecta la position del text y hace que parezca que no está centrado verticalmente. Logré centrar el text en la vista deshabilitando el desplazamiento y estableciendo la inserción 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 desencryption, el cursor todavía no está centrado antes de que comience la tipografía, pero el text se centra de inmediato cuando empiezo a escribir.

He encontrado un enfoque más, obteniendo una vista con el text de las subvenciones de UITextView y configurándola en el método layoutSubview de una subclass:

 - (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); } 
 [firstNameTextField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];