Tengo un UITextView
en mi aplicación iOS, que muestra una gran cantidad de texto.
Luego estoy paginando este texto usando el parámetro de margen de desplazamiento de UITextView
.
Mi problema es que el relleno del archivo UITextView
confunde mis cálculos, ya que parece ser diferente según el tamaño de fuente y la tipografía que uso.
Por lo tanto, planteo la pregunta: ¿es posible eliminar el relleno que rodea el contenido de la UITextView
?
¡Esperamos escuchar sus respuestas!
ios
iphone
cocoa-touch
uikit
uitextview
sniurkst
fuente
fuente
Respuestas:
Actualizado para 2019
Es uno de los errores más tontos en iOS.
La clase dada aquí
UITextViewFixed
es generalmente la solución más razonable en general.Aquí está la clase:
¡No olvide desactivar scrollEnabled en el Inspector!
La solución funciona correctamente en storyboard
La solución funciona correctamente en tiempo de ejecución
Eso es todo, ya terminaste.
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 ,
UITextViewFixed
generalmente hace todo lo que necesita.(Un ejemplo común de cambiar la altura sobre la marcha es cambiarlo a medida que el usuario escribe).
Aquí está el UITextView roto de Apple ...
Aqui esta
UITextViewFixed
:Tenga en cuenta que, por supuesto, debe
apague scrollEnabled en el Inspector!
¡No olvides desactivar scrollEnabled! :)
Algunos problemas adicionales
(1) En algunos casos inusuales, por ejemplo, algunos casos de tablas con alturas de celda flexibles y dinámicamente cambiantes, Apple hace algo extraño: agregan espacio adicional en la parte inferior . ¡No realmente! Esta tendría que ser una de las cosas más irritantes en iOS.
Aquí hay una "solución rápida" para agregar a lo anterior que generalmente ayuda con esa locura.
(2) A veces, para solucionar otro error sutil de Apple, debes agregar esto:
(3) Podría decirse que deberíamos agregar:
justo después
.lineFragmentPadding = 0
deUITextViewFixed
.Sin embargo ... lo creas o no ... ¡ simplemente no funciona en el iOS actual! (Revisado en 2019). Puede ser necesario agregar esa línea en el futuro.
El hecho de que
UITextView
se rompa en iOS es una de las cosas más extrañas en toda la informática móvil. ¡Diez años de aniversario de esta pregunta y aún no se ha solucionado!Finalmente, aquí hay un consejo algo similar para el campo de texto : https://stackoverflow.com/a/43099816/294884
Sugerencia completamente al azar: cómo agregar el "..." al final
A menudo está utilizando un UITextView "como un UILabel". Por lo tanto, desea que trunque el texto usando puntos suspensivos "..."
Si es así, agregue una tercera línea de código en la "configuración":
Sugerencia práctica si desea altura cero, cuando no hay texto
A menudo utiliza una vista de texto para mostrar solo texto. Entonces, el usuario en realidad no puede editar nada. Utiliza líneas "0" para indicar que la vista de texto cambiará automáticamente la altura dependiendo de cuántas líneas de texto.
Eso es genial, pero si no hay texto , ¡lamentablemente obtienes la misma altura que si hubiera una línea de texto ! La vista de texto nunca "desaparece".
Si desea que "desaparezca", simplemente agregue esto
(Lo hice '1' para que quede claro lo que está sucediendo, '0' está bien).
¿Qué hay de UILabel?
Cuando solo muestra texto, UILabel tiene muchas ventajas sobre UITextView. UILabel no sufre los problemas descritos en esta página de control de calidad. De hecho, la razón por la que todos "nos rendimos" y usamos UITextView es que es difícil trabajar con UILabel. En particular, es ridículamente difícil agregar relleno , correctamente, a UILabel. De hecho, aquí hay una discusión completa sobre cómo "finalmente" agregar correctamente el relleno a UILabel: https://stackoverflow.com/a/58876988/294884 En algunos casos, si está haciendo un diseño difícil con celdas de altura dinámica, a veces es mejor hacerlo de la manera difícil con UILabel.
fuente
self.textView.isScrollEnabled = false
dentroviewDidLayoutSubviews()
y eso también funcionó. A Apple simplemente le gusta hacernos saltar a través de aros :)translatesAutoresizingMaskIntoConstraints
. Con esta respuesta sola, no pude eliminar todos los márgenes (algunos márgenes inferiores extraños se resistieron a desaparecer) en una jerarquía de vistas usando el diseño automático. También se ocupa del cálculo de los tamaños de vista usandosystemLayoutSizeFitting
, que anteriormente devolvió un tamaño no válido debido alUITextView
Para iOS 7.0, descubrí que el truco contentInset ya no funciona. Este es el código que utilicé para deshacerme del margen / relleno en iOS 7.
Esto lleva el borde izquierdo del texto al borde izquierdo del contenedor:
Esto hace que la parte superior del texto se alinee con la parte superior del contenedor.
Ambas líneas son necesarias para eliminar completamente el margen / relleno.
fuente
self.descriptionTextView.textContainerInset = UIEdgeInsetsZero;
lineFragmentPadding
en 0 es la magia que estaba buscando. No tengo idea de por qué Apple hace que sea tan difícil alinear el contenido de UITextView con otros controles.lineFragmentPadding
no tiene la intención de modificar los márgenes. De los documentos El relleno de fragmentos de línea no está diseñado para expresar márgenes de texto. En su lugar, debe usar inserciones en su vista de texto, ajustar los atributos de margen de párrafo o cambiar la posición de la vista de texto dentro de su supervista.Esta solución se escribió en 2009 cuando se lanzó IOS 3.0. Ya no se aplica.
Me encontré exactamente con el mismo problema, al final tuve que terminar usando
donde nameField es a
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 a la izquierda quede al ras 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 la alineación predeterminada, es decir.Alinear a la derecha, por ejemplo, y el
UIEdgeInsetsMake
parece que no tiene ningún impacto en el borde derecho.Al menos, el uso de la propiedad .contentInset le permite colocar sus campos con las posiciones "correctas" y acomodar las desviaciones sin compensar su
UITextViews
.fuente
A partir de algunas de las buenas respuestas ya dadas, aquí hay una solución puramente basada en Storyboard / Interface Builder que funciona en iOS 7.0+
Establezca los atributos de tiempo de ejecución definidos por el usuario de UITextView para las siguientes claves:
fuente
En iOS 5
UIEdgeInsetsMake(-8,-8,-8,-8);
parece funcionar muy bien.fuente
Definitivamente evitaría cualquier respuesta que implique valores codificados, ya que los márgenes reales pueden cambiar con la configuración del tamaño de fuente del usuario, etc.
Aquí está la respuesta de @ user1687195, escrita sin modificar el
textContainer.lineFragmentPadding
(porque los documentos indican que este no es el uso previsto).Esto funciona muy bien para iOS 7 y versiones posteriores.
Este es efectivamente el mismo resultado, solo un poco más limpio, ya que no hace un mal uso de la propiedad lineFragmentPadding.
fuente
self.textView.textContainer.lineFragmentPadding = 0;
lineFragmentPadding
no está destinado a controlar los márgenes. Por eso se supone que debes usartextContainerInset
.Solución Storyboard o Interface Builder que utiliza atributos de tiempo de ejecución definidos por el usuario :
Las capturas de pantalla son de iOS 7.1 y iOS 6.1 con
contentInset = {{-10, -5}, {0, 0}}
.fuente
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 utilizarNSLayoutManager
:Esto proporciona el contenido desplazable total, que puede ser más grande que el
UITextView
marco del archivo. Descubrí que esto es mucho más preciso quetextView.contentSize
ya que en realidad calcula cuánto espacio ocupa el texto. Por ejemplo, dado un vacíoUITextView
:Altura de la línea
UIFont
tiene una propiedad que le permite obtener rápidamente la altura de la línea para la fuente dada. Para que pueda encontrar rápidamente la altura de la línea del texto en suUITextView
con:Cálculo del tamaño de texto visible
Determinar la cantidad de texto que es realmente visible es importante para manejar un efecto de "paginación".
UITextView
tiene una propiedad llamadatextContainerInset
que en realidad es un margen entreUITextView.frame
el texto real y el propio. Para calcular la altura real del marco visible, puede realizar los siguientes cálculos:Determinación del tamaño de paginación
Por último, ahora que tiene el tamaño de texto visible y el contenido, puede determinar rápidamente cuáles deberían ser sus compensaciones restando el
textHeight
detextSize
:Utilizando todos estos métodos, no toqué mis inserciones y pude ir al cursor o en cualquier parte del texto que quisiera.
fuente
puedes usar
textContainerInset
propiedad deUITextView
:textView.textContainerInset = UIEdgeInsetsMake (10, 10, 10, 10);
(arriba a la izquierda, abajo a la derecha)
fuente
textContainerInset
propiedad no me funciona cuando quiero cambiarlo a un nuevo valor; consulte stackoverflow.com/questions/19422578/… .Para iOS 10, la siguiente línea funciona para la eliminación del relleno superior e inferior.
fuente
UIEdgeInset.zero
funciona utilizando XCode 8.3 y iOS 10.3 SimulatorÚltimo Swift:
fuente
Aquí hay una versión actualizada de la muy útil respuesta de Fattie. Agrega 2 líneas importantes que me ayudaron a que el diseño funcionara en iOS 10 y 11 (y probablemente también en las más bajas):
¡Las líneas importantes son las dos
translatesAutoresizingMaskIntoConstraints = <true/false>
declaraciones!¡Esto sorprendentemente elimina 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 utilizando elsizeThatFits
método que se menciona en la respuesta aceptada.Al tocar el textView de repente, el extraño margen inferior desapareció y todo parecía como debería, pero solo tan pronto como el textView tiene
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 con las 2 líneas de
setup()
intercalado entre las dostranslatesAutoresizingMaskIntoConstraints
llamadas.Esto, por ejemplo, es muy útil al calcular el marco de una vista usando
systemLayoutSizeFitting
aUIView
. ¡Devuelve el tamaño correcto (que anteriormente no tenía)!Como en la respuesta original mencionada:
¡No olvide desactivar scrollEnabled en el Inspector!
Esa solución funciona correctamente en storyboard, así como en tiempo de ejecución.
Eso es todo, ¡ahora estás realmente listo!
fuente
Para swift 4, Xcode 9
Utilice la siguiente función para cambiar el margen / relleno del texto en UITextView
entonces en este caso es
fuente
Al hacer la solución insertada, 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 forma segura de fuego que encontré fue poner la vista de texto dentro de otra vista que está recortada a límites.
fuente
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.
fuente
Para mí (iOS 11 y Xcode 9.4.1) lo que funcionó mágicamente fue configurar la propiedad textView.font al
UIFont.preferred(forTextStyle:UIFontTextStyle)
estilo y también la primera respuesta mencionada por @Fattie. Pero la respuesta @Fattie no funcionó hasta que configuré la propiedad textView.font, de lo contrario, UITextView sigue comportándose de manera errática.fuente
En caso de que alguien busque la última versión de Swift, el siguiente código funciona bien con Xcode 10.2 y Swift 4.2
fuente
He encontrado un enfoque más, obtener vista con texto de las subvistas de UITextView y configurarlo en el método layoutSubview de una subclase:
fuente
El desplazamiento textView también afecta la posición del texto y hace que parezca que no está centrado verticalmente. Logré centrar el texto en la vista desactivando el desplazamiento y configurando el recuadro superior en 0:
Por alguna razón aún no lo he descubierto, el cursor todavía no está centrado antes de que comience a escribir, pero el texto se centra inmediatamente cuando empiezo a escribir.
fuente
En caso de que desee establecer una cadena HTML y evitar el relleno inferior, asegúrese de no utilizar etiquetas de bloque, es decir, div, p.
En mi caso, esta fue la razón. Puede probarlo fácilmente reemplazando las ocurrencias de las etiquetas de bloque con, por ejemplo, la etiqueta span.
fuente
Para SwiftUI
Si está haciendo su propio TextView usando
UIViewRepresentable
y desea controlar el relleno, en sumakeUIView
función, simplemente haga:uiTextView.textContainerInset = UIEdgeInsets(top: 10, left: 18, bottom: 0, right: 18)
o lo que quieras
fuente
fuente