Estoy tratando de obtener el rect para una cadena atribuida, pero la llamada boundingRectWithSize no respeta el tamaño que paso y devuelve un rect con una altura de línea única en lugar de una altura grande (es una cadena larga). He experimentado pasando un valor muy grande para la altura y también 0 como en el código a continuación, pero el rect devuelto es siempre el mismo.
CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
options:NSStringDrawingUsesDeviceMetrics
context:nil];
¿Está roto o necesito hacer algo más para que devuelva un rect para el texto envuelto?
objective-c
nsattributedstring
RunLoop
fuente
fuente
lineBreakMode
?Respuestas:
Parece que no estabas proporcionando las opciones correctas. Para envolver etiquetas, proporcione al menos:
Nota: si el ancho del texto original es inferior a 300.f, no habrá ajuste de línea, así que asegúrese de que el tamaño del límite sea correcto, de lo contrario, obtendrá resultados incorrectos.
fuente
ceilf(paragraphRect.size.height)
para que se redondee. Me olvido de esto todo el tiempo y me pregunto por qué mis etiquetas todavía están recortadas.boundingRectWithSize:
envuelvo mis cálculos en CGRectIntegral () queCGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers
, en este caso, redondeará la altura y el ancho para garantizar que no se produzca recorte si la altura o el ancho son un valor fraccional.Por alguna razón, boundingRectWithSize siempre devuelve un tamaño incorrecto. Descubrí una solución. Hay un método para UItextView -sizeThatFits que devuelve el tamaño adecuado para el conjunto de texto. Entonces, en lugar de utilizar boundingRectWithSize, cree un UITextView, con un marco aleatorio, y llame a su sizeThatFits con el ancho respectivo y la altura CGFLOAT_MAX. Devuelve el tamaño que tendrá la altura adecuada.
Si está calculando el tamaño en un ciclo while, no olvide agregarlo en un grupo de liberación automática, ya que habrá un número de UITextView creado, la memoria de tiempo de ejecución de la aplicación aumentará si no utilizamos la liberación automática.
fuente
UITextView
tantas veces comoheightForRowAtIndexPath
se llama al método? toma tiempoEd McManus ciertamente ha proporcionado una clave para que esto funcione. Encontré un caso que no funciona
rect no tendrá la altura correcta. Tenga en cuenta que anotherString (que se adjunta a la cadena ) se ha inicializado sin un diccionario de atributos. Este es un inicializador legítimo para anotherString pero boundingRectWithSize: no proporciona un tamaño exacto en este caso.
fuente
NSMutableAttributedString
sin atributos y estaba obteniendo un tamaño incorrecto.Mi decisión final después de una larga investigación: ¡la
- boundingRectWithSize
función devuelve el tamaño correcto solo para la secuencia ininterrumpida de caracteres! En caso de que la cadena contenga espacios u otra cosa (llamada por Apple "Algunos de los glifos"), ¡es imposible obtener el tamaño real de rect necesario para mostrar el texto!He reemplazado espacios en mis cadenas por letras e inmediatamente obtuve el resultado correcto.
Apple dice aquí: https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize
"Este método devuelve los límites reales de los glifos en la cadena. Algunos de los glifos (espacios, por ejemplo) pueden solapar las restricciones de diseño especificadas por el tamaño pasado, por lo que en algunos casos el valor de ancho del componente de tamaño de el valor devuelto
CGRect
puede exceder el valor del ancho del parámetro de tamaño ".Por lo tanto, es necesario encontrar otra forma de calcular el rect real ...
Después de un largo proceso de investigación, la solución finalmente se encontró. No estoy seguro de que funcione bien para todos los casos relacionados
UITextView
, ¡pero se detectó lo principal e importante!boundingRectWithSize
La función así comoCTFramesetterSuggestFrameSizeWithConstraints
(y muchos otros métodos) calcularán el tamaño y la porción de texto correcta cuando se usa el rectángulo correcto. Por ejemplo,UITextView
tienetextView.bounds.size.width
- y este valor no es un rectángulo real utilizado por el sistema cuando se dibuja textoUITextView
.Encontré un parámetro muy interesante y realicé un cálculo simple en el código:
Y la magia funciona: ¡todos mis textos calculados correctamente ahora! ¡Disfrutar!
fuente
Swift cuatro versiones
La medición del texto con CTFramesetter funciona mejor ya que proporciona tamaños enteros y maneja bien los emoji y otros caracteres unicode.
fuente
No tuve suerte con ninguna de estas sugerencias. Mi cadena contenía viñetas Unicode y sospecho que estaban causando dolor en el cálculo. Noté que UITextView estaba manejando bien el dibujo, así que busqué eso para aprovechar su cálculo. Hice lo siguiente, que probablemente no sea tan óptimo como los métodos de dibujo NSString, pero al menos es preciso. También es un poco más óptimo que inicializar un UITextView solo para llamar
-sizeThatFits:
.fuente
En caso de que desee obtener un cuadro delimitador truncando la cola, esta pregunta puede ayudarlo.
fuente
Resulta que CADA parte de una NSAttributedString debe tener un diccionario establecido con al menos NSFontAttributeName y NSForegroundColorAttributeName establecido, si desea que limitingRectWithSize realmente funcione.
No veo eso documentado en ningún lado.
fuente
@warrenm Lamento decir que el método de creación de marcos no funcionó para mí.
Obtuve esto. Esta función puede ayudarnos a determinar el tamaño de fotograma necesario para un rango de cadena de un NSAttributedString en iphone / Ipad SDK para un ancho dado:
Se puede usar para una altura dinámica de celdas UITableView
Gracias a HADDAD ISSA >>> http://haddadissa.blogspot.in/2010/09/compute-needed-heigh-for-fixed-width-of.html
fuente
#import <CoreText/CoreText.h>
Descubrí que la solución preferida no maneja los saltos de línea.
He encontrado que este enfoque funciona en todos los casos:
fuente
He tenido el mismo problema al no obtener un tamaño exacto utilizando estas técnicas y he cambiado mi enfoque para que funcione.
Tengo una cadena larga atribuida que he estado tratando de ajustar en una vista de desplazamiento para que se muestre correctamente sin truncarse. Lo que hice para que el texto funcionara de manera confiable fue no establecer la altura como una restricción y, en cambio, permití que el tamaño intrínseco se hiciera cargo. Ahora el texto se muestra correctamente sin ser truncado y no tengo que calcular la altura.
Supongo que si tuviera que obtener la altura de manera confiable, crearía una vista que está oculta y estas restricciones y obtendría la altura del marco una vez que se apliquen las restricciones.
fuente
Llegué un poco tarde al juego, pero he estado tratando de encontrar una manera que funcione para encontrar el cuadro delimitador que se ajuste alrededor de una cadena atribuida para hacer un anillo de enfoque como lo hace editar un archivo en Finder. todo lo que había intentado falló cuando hay espacios al final de la cadena o múltiples espacios dentro de la cadena.
boundingRectWithSize
falla miserablemente por esto y por esoCTFramesetterCreateWithAttributedString
.El uso
NSLayoutManager
del siguiente código parece hacer el truco en todos los casos que he encontrado hasta ahora y devuelve un rect que limita perfectamente la cadena. Bonificación: si selecciona el texto, los bordes de la selección van hasta los límites del rectángulo devuelto. El siguiente código utiliza el layoutManager de aNSTextView
.fuente
Funciona en todas las fuentes perfectamente!
fuente
Tuve el mismo problema, pero reconocí que la altura restringida se ha configurado correctamente. Entonces hice lo siguiente:
fuente
Intenté todo en esta página y todavía tenía un caso para un UILabel que no se formateaba correctamente. En realidad, establecer el texto atribuido en la etiqueta finalmente solucionó el problema.
fuente
Una cosa que noté es que el rectángulo que regresaría
(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context
tendría un ancho mayor que el que pasé. Cuando esto sucediera, mi cadena se truncaría. Lo resolví así:Para un poco más de contexto; Tenía texto de varias líneas e intentaba encontrar la altura correcta para mostrarlo. BoundRectWithSize a veces devolvía un ancho mayor que el que especificaría, por lo tanto, cuando utilicé mi pasado en ancho y la altura calculada para mostrar mi texto, se truncaría Desde la prueba, cuando la funciónINDINGRectWithSize utilizaba el ancho incorrecto, la cantidad por la que acortaría la altura era de 1 línea. Entonces verificaría si el ancho era mayor y, de ser así, agregaría lineHeight de la fuente para proporcionar suficiente espacio para evitar el truncamiento.
fuente
Si el marco de la etiqueta no agrega 10, ¡este método nunca funcionará! ¡Espero que esto le pueda ayudar! buena suerte.
fuente
}
fuente
Me gustaría agregar mis pensamientos ya que tenía exactamente el mismo problema.
Estaba usando
UITextView
porque tenía una mejor alineación de texto (justificar, que en ese momento no estaba disponibleUILabel
), pero para "simular" no interactivo-no desplazableUILabel
, desactivaba el desplazamiento completo, el rebote y la interacción del usuario .Por supuesto, el problema era que el texto era dinámico, y aunque el ancho sería fijo, la altura debería recalcularse cada vez que estableciera un nuevo valor de texto.
boundingRectWithSize
no me funcionó bien, por lo que pude ver,UITextView
fue agregar un margen en la parte superior queboundingRectWithSize
no entraría en un conteo, por lo tanto, la altura recuperadaboundingRectWithSize
fue menor de lo que debería ser.Como el texto no debía actualizarse rápidamente, solo se usa para obtener información que puede actualizarse cada 2-3 segundos como máximo, he decidido seguir el siguiente enfoque:
* El código anterior no se copia directamente de mi fuente, tuve que ajustarlo / borrarlo de un montón de otras cosas que no son necesarias para este artículo. No lo tome por copiar-pegar-y-va a funcionar-código.
La desventaja obvia es que tiene asignación y liberación, para cada llamada.
Pero, la ventaja es que evita depender de la compatibilidad entre la forma en que boundingRectWithSize dibuja el texto y calcula su tamaño y la implementación del dibujo de texto
UITextView
(oUILabel
que también puede usar simplemente reemplazarUITextView
conUILabel
). De esta manera, se evitan los "errores" que Apple pueda tener.PD: Parece que no deberías necesitar esta "temperatura"
UITextView
y puedes pedirsizeThatFits
directamente desde el objetivo, sin embargo, eso no funcionó para mí. Aunque la lógica diría que debería funcionar y la asignación / liberación de temporalUITextView
no es necesaria, no lo hizo. Pero esta solución funcionó a la perfección para cualquier texto que agregue.fuente
Ok, así que pasé mucho tiempo depurando esto. Descubrí que la altura máxima del texto según lo definido por mi
boundingRectWithSize
permite que el texto seaUITextView
más bajo que el tamaño del marco.En mi caso, el marco es como máximo 140 puntos, pero el UITextView tolera textos como máximo 131 puntos.
Tuve que resolver eso manualmente y codificar la altura máxima "real".
Aquí está mi solución:
fuente