Cálculo de la altura del texto multilínea para UILabel/ UITableViewCell: resultados diferentes al calcular vs dibujo real


Este tema general se ha preguntado aquí varias veces: cómo renderizar UITableViewCells con una cantidad variable de texto y, por lo tanto, una altura variable. La respuesta canónica es: se calcula la altura en el delegado del controlador de vista de tabla en heightForRowAtIndexPath usando sizeWithFont:constrainedToSize: lineBreakMode:. Más tarde, la celda se dibuja, y se usa algo como [label sizeToFit] si es necesario, y todo funciona como magia.

Mi problema: Estoy recibiendo envoltura para algunas células porque sizeWithFont: devuelve diferentes dimensiones del dibujo real.

Un ejemplo específico:

El texto es este: "La gente olvida que @BillGates tenía una pizarra sexy de 1/4 de pulgada de espesor en 1993 de NEC. Pase lo que pase esta semana NO será sobre hardware!"

CGSize theSize = [text sizeWithFont:[UIFont systemFontOfSize:17.0f] constrainedToSize:CGSizeMake(310.0f, FLT_MAX) lineBreakMode:UILineBreakModeWordWrap];
NSLog(@"calculated size for %@: %f, %f",text, theSize.width, theSize.height);

Esto devuelve: 306.000000, 84.000000. (Es decir, 4 filas con fuente 17px y espacio de línea 4px, 21px en primer lugar.) Bueno.

Sin embargo, más tarde cuando realmente se dibuja la celda:

label = (UILabel *)[cell viewWithTag:3];
label.text = [NSString stringWithFormat:@"%@", text];
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont systemFontOfSize:17.0f];
CGSize labelSize;   
labelSize = label.frame.size;
NSLog(@"label size before resizing: %f, %f", labelSize.width, labelSize.height);
[label sizeToFit];
labelSize = label.frame.size;
NSLog(@"label size after resizing: %f, %f for text %@", labelSize.width, labelSize.height,text);

(UILabel se carga como parte de UITableViewCell de NIB. En IB lo puse a 310px de ancho.)

Esto debe devolver exactamente el mismo tamaño que el anterior. En su lugar, obtengo 281.000000, 105.000000 como las dimensiones después de la llamada sizeToFit. Ahora son 5 líneas en el momento del dibujo en lugar de 4, y el texto se derrama, veo el desbordamiento en la interfaz de usuario.

Por lo tanto, para el mismo texto, estoy obteniendo dos dimensiones diferentes calculadas, y no puedo entenderlo. ¿Es algo sobre UILabel? ¿Tiene algún margen interior? Esto sigue sucediendo para algunos textos pero no para otros, y no lo he rastreado a algo particular sobre las cuerdas; parece aleatorio. Este tema destaca que hay dos pasadas de procesamiento: calcular la altura frente al dibujo real. Esto es consistente con lo que estoy viendo. Pero no entiendo qué está pasando exactamente o cómo arreglarlo.

La pregunta: ¿por qué veo dos tamaños calculados diferentes, y cómo lo arreglo?

Author: Community, 2010-01-26

3 answers

Por supuesto, la solución es obvia 30 segundos después de la publicación. Tal vez útil para los demás también...

El tamaño de sizeWithFont: era correcto. Los tamaños que calculé de la manera anterior eran incorrectos, porque [label sizeToFit] reduce el ancho del marco de la etiqueta. En llamadas posteriores al mismo código, comenzó con el marco que ya puede haber sido reducido.

La solución era simplemente restablecer el marco width a un ancho bueno conocido antes de dimensionarlo para ajustarse:

CGRect labelFrame = label.frame;
labelFrame.size.width = 310;
label.frame = labelFrame;
[label sizeToFit];
 36
Author: Jaanus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-26 13:19:05

Para las etiquetas multilínea es necesario establecer

cell.textLabel.numberOfLines = 0;

Y luego

[cell.textLabel sizeToFit];

Pero para una vista bonita necesita agregar algunos píxeles de relleno. Y su aplicación será impresionante!

 11
Author: Oleg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-10 03:45:40
 titleSize = [title sizeWithFont:[UIFont systemFontOfSize:(CGFloat)17.0]
                                constrainedToSize:CGSizeMake(280, 2000)
                                    lineBreakMode:NSLineBreakByWordWrapping];
 6
Author: Aswathi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-12 05:30:54