Tengo una UITableView
con un personalizado UITableViewCell
definido en un guión gráfico usando diseño automático. La celda tiene varias multilíneas UILabels
.
Los UITableView
parece altos de celdas adecuadamente calcular, pero para las primeras células que la altura no se divide adecuadamente entre las etiquetas. Después de desplazarse un poco, todo funciona como se esperaba (incluso las celdas que inicialmente eran incorrectas).
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
¿Hay algo que me pueda faltar, que esté causando que el diseño automático no pueda hacer su trabajo las primeras veces?
Creé un proyecto de muestra que demuestra este comportamiento.
ios
uitableview
ios8
autolayout
ios-autolayout
blackp
fuente
fuente
Respuestas:
No sé que esto esté claramente documentado o no, pero agregar
[cell layoutIfNeeded]
antes de devolver la celda resuelve su problema.fuente
-layoutIfNeeded
en el celular-awakeFromNib
. Preferiría llamar sololayoutIfNeeded
donde sé por qué es necesario.Esto funcionó para mí cuando otras soluciones similares no lo hicieron:
Esto parece un error real ya que estoy muy familiarizado con AutoLayout y cómo usar UITableViewAutomaticDimension, sin embargo, ocasionalmente me encuentro con este problema. Me alegro de haber encontrado finalmente algo que funciona como solución.
fuente
super.didMoveToSuperview()
didMoveToSuperview
: "La implementación predeterminada de este método no hace nada".Adición
[cell layoutIfNeeded]
encellForRowAtIndexPath
no funciona para células que se desplazan inicialmente fuera de la vista.Tampoco precederlo con
[cell setNeedsLayout]
.Todavía tiene que desplazar ciertas celdas hacia afuera y volver a verlas para que cambien de tamaño correctamente.
Esto es bastante frustrante ya que la mayoría de los desarrolladores tienen celdas de tipo dinámico, autodiseño y de tamaño propio funcionando correctamente, excepto en este caso molesto. Este error afecta a todos mis controladores de vista de tabla "más altos".
fuente
[cell layoutSubviews]
lugar de layoutIfNeeded podría ser una posible solución. Consulte stackoverflow.com/a/33515872/1474113Tuve la misma experiencia en uno de mis proyectos.
¿Por qué sucede?
Celda diseñada en Storyboard con algo de ancho para algún dispositivo. Por ejemplo 400px. Por ejemplo, su etiqueta tiene el mismo ancho. Cuando se carga desde el guión gráfico, tiene un ancho de 400 px.
Aquí hay un problema:
tableView:heightForRowAtIndexPath:
llamado antes del diseño de la celda, sus subvistas.Entonces calculó la altura de la etiqueta y la celda con un ancho de 400px. Pero se ejecuta en un dispositivo con pantalla, por ejemplo, 320px. Y esta altura calculada automáticamente es incorrecta. El hecho de que la celda
layoutSubviews
ocurra solo después detableView:heightForRowAtIndexPath:
Incluso si configurapreferredMaxLayoutWidth
su etiqueta manualmentelayoutSubviews
no ayuda.Mi solución:
1) Subclase
UITableView
y anulacióndequeueReusableCellWithIdentifier:forIndexPath:
. Establezca el ancho de la celda igual al ancho de la tabla y fuerce el diseño de la celda.2) Subclase
UITableViewCell
. ConfigurepreferredMaxLayoutWidth
manualmente sus etiquetas en formatolayoutSubviews
. También necesita un diseño manualcontentView
, porque no se distribuye automáticamente después del cambio del marco de la celda (no sé por qué, pero lo es)fuente
cell.frame.size.width = tableview.frame.width
luegocell.layoutIfNeeded()
en lacellForRowAt
función hizo el truco para míTengo un problema similar, en la primera carga, no se calculó la altura de la fila, pero después de desplazarme un poco o ir a otra pantalla y vuelvo a esta pantalla, se calculan las filas. En la primera carga, mis artículos se cargan desde Internet y en la segunda carga, mis artículos se cargan primero desde Core Data y se vuelven a cargar desde Internet, y noté que la altura de las filas se calcula en la recarga desde Internet. Así que noté que cuando se llama a tableView.reloadData () durante la animación de segue (el mismo problema con push y present segue), no se calculó la altura de la fila. Así que oculté la vista de tabla en la inicialización de la vista y puse un cargador de actividad para evitar un efecto desagradable para el usuario y llamé a tableView.reloadData después de 300ms y ahora el problema está resuelto. Creo que es un error de UIKit, pero esta solución funciona.
Puse estas líneas (Swift 3.0) en mi controlador de finalización de carga de artículos
Esto explica por qué, para algunas personas, poner un reloadData en el diseño.
fuente
ninguna de las soluciones anteriores funcionó para mí, lo que funcionó es esta receta de una magia: llámalos en este orden:
tableView.reloadData()
tableView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates()
mis datos de tableView se completan desde un servicio web, en la devolución de llamada de la conexión escribo las líneas anteriores.
fuente
En mi caso, la última línea de UILabel se truncó cuando se mostró la celda por primera vez. Ocurrió de forma bastante aleatoria y la única forma de dimensionarlo correctamente era desplazar la celda fuera de la vista y traerla de vuelta. Probé todas las soluciones posibles mostradas hasta ahora (layoutIfNeeded..reloadData) pero nada funcionó para mí. El truco consistía en establecer "Autoencogimiento" en Escala de fuente mínima (0,5 para mí). Darle una oportunidad
fuente
Agregue una restricción para todo el contenido dentro de una celda personalizada de vista de tabla, luego estime la altura de fila de vista de tabla y establezca la altura de fila en dimensión automática con una carga viewdid:
Para solucionar ese problema de carga inicial, aplique el método layoutIfNeeded en una celda de vista de tabla personalizada:
fuente
estimatedRowHeight
un valor> 0 y noUITableViewAutomaticDimension
(que es -1), de lo contrario, la altura de fila automática no funcionará.Probé la mayoría de las respuestas a esta pregunta y no pude hacer que ninguna funcionara. La única solución funcional que encontré fue agregar lo siguiente a mi
UITableViewController
subclase:Se
UIView.performWithoutAnimation
requiere la llamada; de lo contrario, verá la animación de vista de tabla normal a medida que se carga el controlador de vista.fuente
viewWillAppear
no funcionó para mí, pero hacerloviewDidAppear
sí.La configuración
preferredMaxLayoutWidth
ayuda en mi caso. yo añadíen mi código.
También consulte El texto de una sola línea toma dos líneas en UILabel y http://openradar.appspot.com/17799811 .
fuente
llamar
cell.layoutIfNeeded()
adentrocellForRowAt
funcionó para mí en ios 10 e ios 11, pero no en ios 9.para que esto funcione también en ios 9, llamo
cell.layoutSubviews()
y funcionó.fuente
Para mí, ninguno de estos enfoques funcionó, pero descubrí que la etiqueta tenía un
Preferred Width
conjunto explícito en Interface Builder. Eliminar eso (desmarcar "Explícito") y luego usarUITableViewAutomaticDimension
funcionó como se esperaba.fuente
Probé todas las soluciones en esta página, pero desmarcar las clases de tamaño de uso y luego verificarlas nuevamente resolvió mi problema.
Editar: desmarcar las clases de tamaño causa muchos problemas en el guión gráfico, así que probé otra solución. Completé mi vista de tabla en los métodos
viewDidLoad
y del controlador de mi vistaviewWillAppear
. Esto resolvió mi problema.fuente
Tengo el problema con el cambio de tamaño de la etiqueta, así que solo
necesito hacer chatTextLabel.text = chatMessage.message chatTextLabel? .UpdateConstraints () después de configurar el texto
// código completo
fuente
En mi caso, estaba actualizando en otro ciclo. Entonces la altura de tableViewCell se actualizó después de que se estableció labelText. Eliminé el bloque asincrónico.
fuente
Solo asegúrese de no configurar el texto de la etiqueta en el método delegado 'willdisplaycell' de la vista de tabla. Establezca el texto de la etiqueta en el método delegado 'cellForRowAtindexPath' para el cálculo dinámico de la altura.
De nada :)
fuente
En mi caso, una vista de pila en la celda estaba causando el problema. Aparentemente es un error. Una vez que lo eliminé, el problema se resolvió.
fuente
El problema es que las celdas iniciales se cargan antes de que tengamos una altura de fila válida. La solución alternativa es forzar la recarga de la tabla cuando aparece la vista.
fuente
Solo para iOS 12+, 2019 en adelante ...
Un ejemplo continuo de la incompetencia extraña ocasional de Apple, donde los problemas continúan literalmente durante años.
Parece ser el caso que
lo arreglará. (Está perdiendo algo de rendimiento, por supuesto).
Así es la vida con Apple.
fuente
En mi caso, el problema con la altura de la celda se produce después de que se carga la vista de la tabla inicial y se lleva a cabo una acción del usuario (tocar un botón en una celda que tiene el efecto de cambiar la altura de la celda). No he podido hacer que la celda cambie su altura a menos que lo haga:
lo intenté
pero eso no funcionó.
fuente
En Swift 3. Tuve que llamar a self.layoutIfNeeded () cada vez que actualizo el texto de la celda reutilizable.
fuente
Ninguna de las soluciones anteriores funcionó, pero la siguiente combinación de sugerencias sí.
Tuve que agregar lo siguiente en viewDidLoad ().
La combinación anterior de reloadData, setNeedsLayout y layoutIfNeeded funcionó, pero no ninguna otra. Sin embargo, podría ser específico de las celdas del proyecto. Y sí, tuve que invocar reloadData dos veces para que funcione.
También configure lo siguiente en viewDidLoad
En tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
fuente
reloadData/beginUpdates/endUpdates/reloadData
también está funcionando;reloadData
debe ser llamado por segunda vez. No es necesario envolverloasync
.Me encontré con este problema y lo arreglaron moviendo mi punto de vista / etiqueta de código de inicialización DE
tableView(willDisplay cell:)
AtableView(cellForRowAt:)
.fuente
willDisplay
tendrá un mejor rendimiento quecellForRowAt
. Use el último solo para instanciar la celda correcta.willDisplay
tiene un mejor rendimiento, se recomienda inicializar la interfaz de usuario de su celdacellForRowAt
cuando el diseño es automático. De hecho, el diseño lo calcula UIKit después de cellForRowAt et antes de willDisplay. Entonces, si la altura de su celda depende de su contenido, inicialice el contenido de la etiqueta (o lo que sea) encellForRowAt
.use el método anterior que devuelve la altura de la fila de forma dinámica. Y asigne la misma altura dinámica a la etiqueta que está utilizando.
Este código le ayuda a encontrar la altura dinámica del texto que se muestra en la etiqueta.
fuente