¿Es posible obtener una altura de encabezado de sección de vista de tabla dinámica usando Auto Layout?

112

Como novedad en iOS 8, puede obtener celdas de vista de tabla 100% dinámicas simplemente configurando la altura de fila estimada, luego diseñe sus elementos en la celda usando Diseño automático. Si el contenido aumenta en altura, la celda también aumentará en altura. Esto es extremadamente útil y me pregunto si se puede lograr la misma hazaña para los encabezados de sección en una vista de tabla.

Se puede, por ejemplo, crear una UIViewen tableView:viewForHeaderInSection:, añadir una UILabelvista secundaria, especificar restricciones de diseño automático para el sello contra la visión, y tienen la vista incremento en la altura para adaptarse a los contenidos de la etiqueta, sin tener que implementar tableView:heightForHeaderInSection:?

La documentación para los viewForHeaderInSectionestados: "Este método solo funciona correctamente cuando también se implementa tableView: heightForHeaderInSection:". No he escuchado si algo ha cambiado para iOS 8.

Si uno no puede hacer eso, ¿cuál es la mejor manera de imitar este comportamiento?

Jordan H
fuente

Respuestas:

275

Esto es posible. Es nuevo junto con las alturas de celda dinámicas implementadas en iOS 8.

Es muy simple. Solo agrega esto en viewDidLoad:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 25;

Luego anule viewForHeaderInSectiony use el diseño automático para restringir los elementos en su vista como mejor le parezca. ¡Eso es! No es necesario implementarlo heightForHeaderInSection. Y en realidad sectionHeaderHeighttampoco es necesario que se indique, solo lo agregué para mayor claridad.

Tenga en cuenta que en iOS 11, las celdas y las vistas de encabezado / pie de página utilizan alturas estimadas de forma predeterminada. Lo único que debe hacer es proporcionar una altura estimada para informar mejor al sistema de lo que puede esperar. El valor predeterminado es, UITableViewAutomaticDimensionpero debe proporcionar una mejor estimación de la altura promedio que tendrán si es posible.

Jordan H
fuente
3
Eso es genial si funciona, pero los documentos no lo mencionan, y tampoco lo hizo la sesión de la WWDC si no recuerdo mal. Los documentos para UITableViewAutomaticDimensiondicen "si devuelve esta constante en tableView:heightForHeaderInSection:o tableView:heightForFooterInSection:, UITableViewusa una altura que se ajuste al valor devuelto de tableView:titleForHeaderInSection:o tableView:titleForFooterInSection:(si el título no lo es nil)".
Aaron Brager
28
Esto no funcionó para mí. El encabezado de mi sección pudo calcular la altura automáticamente, pero se superpone a las celdas de la sección. Estoy configurando mi vista de encabezado usando un archivo xib y estableciendo mis restricciones en el generador de interfaces. ¿Ese es mi problema? ¿Dónde están creando las limitaciones? ¡Gracias!
CoBrA2168
5
Como se prometió, aquí está el código de muestra: github.com/ebetabox/DynamicCellSectionHeight
PakitoV
10
Otro punto clave aquí, las celdas de su tabla también deben configurarse para el cálculo de altura automática (UITableViewAutomaticDimension) para que funcione en las secciones.
Bob Spryn
9
Debe tener estimatedSectionHeaderHeighto tableView:estimatedHeightForHeaderInSection:AND sectionHeaderHeighto tableView:heightForHeaderInSection:. Además, si está utilizando los métodos de delegado, debe devolver un valor mayor que 1,00 para la estimación (comportamiento completamente indocumentado); de lo contrario, NO se llamará al delegado de altura y se utilizará la altura del encabezado de la vista de tabla predeterminada.
Vadoff
29

Esto se puede lograr configurando (o devolviendo) la estimatedSectionHeaderHeightvista en su mesa.

Si el encabezado de su sección se superpone a sus celdas después de la configuraciónestimatedSectionHeaderHeight , asegúrese de que está usando unestimatedRowHeight .

(Estoy agregando esta respuesta porque el segundo párrafo contiene una respuesta a un problema que se puede encontrar después de leer todos los comentarios que algunos podrían pasar por alto).

Clay Ellis
fuente
1
Gracias, después de configurar estimatedRowHeightesto funciona como un encanto :)
sz ashik
1
Esto es cierto incluso si NO está utilizando UITableViewAutomaticDimension para filas. Gracias por ahorrarme una hora.
Ryan Romanchuk
14

Me quedé atascado en el mismo problema en el que el encabezado obtenía una altura cero hasta y, a menos que proporcione una altura fija en el delegado para heighForHeaderInSection .

Probé muchas soluciones que incluyen

self.tableView.sectionHeaderHeight = UITableView.automaticDimension
self.tableView.estimatedSectionHeaderHeight = 73

Pero nada funcionó. Mi celular también estaba usando diseños automáticos adecuados. Las filas cambiaban su altura dinámicamente mediante el siguiente código, pero el encabezado de la sección no.

self.tableView.estimatedRowHeight = 135
self.tableView.rowHeight = UITableView.automaticDimension

La solución es extremadamente simple y extraña también, pero tuve que implementar los métodos delegados en lugar del código de 1 línea para el estimatedSectionHeaderHeighty sectionHeaderHeightque es el siguiente para mi caso.

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    UITableView.automaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
    73
}
Ahsan Ebrahim
fuente
11

Rápido 4+

trabajando (probado 100%)

Si necesita tanto la sección como la fila con altura dinámica basada en el contenido, puede usar el siguiente código:

En viewDidLoad () escribe estas líneas:

    self.globalTableView.estimatedRowHeight = 20
    self.globalTableView.rowHeight = UITableView.automaticDimension

    self.globalTableView.sectionHeaderHeight =  UITableView.automaticDimension
    self.globalTableView.estimatedSectionHeaderHeight = 25;

Ahora hemos establecido la altura de la fila y la altura de la sección mediante el uso de los métodos Delegados de UITableView:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
   {
       return UITableView.automaticDimension
   }
   func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

       return UITableView.automaticDimension

   }
Señor Javed Multani
fuente
NOTA a esta gran respuesta. A partir de 2020 , parece estar bien usar SOLAMENTE las cuatro propiedades en viewDidLoad.
Fattie
NOTA a esta gran respuesta. A partir de 2020 , SÍ necesita las dos líneas "inútiles" que dan una altura estimada (digamos, 20 más o menos).
Fattie
6

Lo intenté

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 25;

pero no tenía el tamaño correcto del encabezado con etiqueta de varias líneas. Agregué esto para resolver mi problema:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Recalculates height
    tableView.beginUpdates()
    tableView.endUpdates()
}
iuriimoz
fuente
defina las funciones de la fuente de datos tableView:estimatedHeightForHeaderInSectiony en tableView:heightForHeaderInSectionlugar de definirlas en viewDidLoad.
Keith Yeoh
Descubrí que la configuración estimatedSectionHeaderHeightsolo es necesaria debajo de iOS 11
doctorBroctor
1

En mi caso:

  1. establecer programáticamente no funciona .

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension.

  1. ambientado en el guión gráfico no funciona .

  2. anular heightForHeaderInSection funcionó .

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return UITableViewAutomaticDimension
}

entorno de prueba:

  • Mac OS 10.13.4
  • XCode Versión 9.4.1
  • Simulador de iPhone 8 Plus
Codus
fuente
0

Sí, me funciona. Tengo que hacer más cambios de la siguiente manera:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label = UILabel()

    label.numberOfLines = 0
    label.text          = my own text

    return label
}
arg_vn
fuente
-2

He modificado iuriimoz respuesta . Recién reemplazado el método viewWillAppear:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 25


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Recalculates height
    tableView.layoutIfNeeded() 
}

También agregue el tableView.layoutIfNeeded () a

override func viewDidAppear(_ animated: Bool) {

    super.viewDidAppear(animated)
    tableView.layoutIfNeeded()
}

Para iOS 10

tableView.beginUpdates()
tableView.endUpdates()

tiene un efecto de animación "desvanecimiento" en la vista

Irina
fuente