ios - resizing - uitableviewautomaticdimension
UILabel en UITableViewCell con diseño automático tiene una altura incorrecta (4)
Tengo un UITableView
con celdas que tienen una altura fija de 100 puntos. Las celdas se crean en un archivo xib que usa 3 restricciones para anclar un UILabel
a los bordes izquierdo, derecho y superior del contentView
de la celda. La prioridad vertical de la etiqueta se establece en 1000 porque quiero que la altura de la celda sea lo más pequeña posible.
Cuando el ancho de la celda en el archivo xib se establece en 320 puntos, al igual que el ancho de tableView en el iPhone, la reproducción automática funciona como se espera. Sin embargo, cuando configuro el ancho de la celda en menos de 320 puntos, obtengo resultados inesperados. (Quiero usar la misma celda en las vistas de tabla que tienen diferentes anchos, por ejemplo, en una aplicación universal)
Por ejemplo: cuando establezco el ancho en 224 puntos y le doy a la etiqueta un texto que ocupa 2 líneas en ese ancho, la altura de la etiqueta aumentará para ajustarse a las 2 líneas, pero cuando la celda se redimensione a 320 puntos para adaptarse una vista de tabla de ese ancho, el texto solo ocupa 1 línea, pero el alto de la etiqueta permanece en 2 líneas.
He puesto un proyecto de muestra en GitHub para demostrar el problema: https://github.com/bluecrowbar/CellLayout
¿Hay alguna manera de hacer que la UILabel
siempre UILabel
tamaño para UILabel
contenido del texto?
¡Estúpido bicho! Perdí casi un día en este problema y finalmente lo resolví con la solución de Steven Vandewghe.
Versión rápida:
override func layoutSubviews() {
super.layoutSubviews()
self.contentView.layoutIfNeeded()
self.myLabel.preferredMaxLayoutWidth = self.myLabel.frame.size.width
}
Añadiendo esto en la subclase de celda funciona:
- (void)layoutSubviews
{
[super layoutSubviews];
[self.contentView layoutIfNeeded];
self.myLabel.preferredMaxLayoutWidth = self.myLabel.frame.size.width;
}
Encontré esto en http://useyourloaf.com/blog/2014/02/14/table-view-cells-with-varying-row-heights.html .
Actualización 1: esta respuesta fue para iOS 7. Creo que el diseño automático en las celdas de vista de tabla es muy poco confiable desde iOS 8, incluso para diseños muy simples. Después de mucha experimentación, (en su mayoría) volví a hacer el diseño manual y el cálculo manual de la altura de la celda.
Actualización 2: he ejecutado algunas pruebas en iOS 9 y parece que UITableViewAutomaticDimension
finalmente funciona como se anuncia. ¡Hurra!
Como está restringiendo el width
la etiqueta, intrinsicContentSize
respeta ese width
y ajusta la height
. Y esto plantea un problema de huevo y gallina:
- El resultado de Auto Layout de la celda depende de la etiqueta
intrinsicContentSize
- El tamaño del contenido
intrinsicContentSize
de la etiqueta depende delwidth
la etiqueta - El
width
la etiqueta depende del resultado del diseño automático de la celda
Entonces, lo que sucede es que el diseño de la celda solo se calcula una vez en la que (2) se basa en el ancho estático en el archivo XIB y esto da como resultado una height
etiqueta incorrecta.
Puedes resolver esto iterando. Es decir, repita el cálculo de Disposición automática una vez que el width
la etiqueta haya sido establecido por el primer cálculo. Algo como esto en tu celda personalizada funcionará:
- (void)drawRect:(CGRect)rect
{
CGSize size = self.myLabel.bounds.size;
// tell the label to size itself based on the current width
[self.myLabel sizeToFit];
if (!CGSizeEqualToSize(size, self.myLabel.bounds.size)) {
[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];
}
[super drawRect:rect];
}
La solución original no funciona de manera confiable:
- (void)layoutSubviews
{
[super layoutSubviews];
// check for need to re-evaluate constraints on next run loop
// cycle after the layout has been finalized
dispatch_async(dispatch_get_main_queue(), ^{
CGSize size = self.myLabel.bounds.size;
// tell the label to size itself based on the current width
[self.myLabel sizeToFit];
if (!CGSizeEqualToSize(size, self.myLabel.bounds.size)) {
[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];
}
});
}
Normalmente agrego estas dos líneas a viewDidLoad ()
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 96
Esto cambiará automáticamente el tamaño de la celda