É possível obter uma altura de cabeçalho de seção de visualização de tabela dinâmica usando Layout automático?

112

Novo no iOS 8, você pode obter células de visualização de tabela 100% dinâmicas simplesmente definindo a altura estimada da linha e, em seguida, faça o layout de seus elementos na célula usando o Layout automático. Se o conteúdo aumentar de altura, a célula também aumentará de altura. Isso é extremamente útil, e estou me perguntando se o mesmo feito pode ser realizado para cabeçalhos de seção em uma visualização de tabela?

Pode-se, por exemplo, criar um UIViewem tableView:viewForHeaderInSection:, adicionar um UILabelsubexibição, especificar restrições de layout automático para a etiqueta contra a visão, e ter o aumento de vista de altura para caber o conteúdo do rótulo, sem ter que implementar tableView:heightForHeaderInSection:?

A documentação para viewForHeaderInSectionestados: "Este método só funciona corretamente quando tableView: heightForHeaderInSection: também é implementado." Não soube se alguma coisa mudou no iOS 8.

Se não for possível fazer isso, qual é a melhor maneira de imitar esse comportamento?

Jordan H
fonte

Respostas:

275

Isso é possível. É novo junto com as alturas de células dinâmicas implementadas no iOS 8.

É muito simples. Basta adicionar isso em viewDidLoad:

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

Em seguida, substitua viewForHeaderInSectione use o Layout automático para restringir os elementos em sua visualização conforme visto o ajuste. É isso aí! Não há necessidade de implementar heightForHeaderInSection. E na verdade osectionHeaderHeight não precisa ser declarado, eu apenas o adicionei para maior clareza.

Observe que no iOS 11, células e visualizações de cabeçalho / rodapé usam alturas estimadas por padrão. A única coisa a fazer é fornecer uma altura estimada para informar melhor ao sistema o que esperar. O valor padrão é, UITableViewAutomaticDimensionmas você deve fornecer uma estimativa melhor que seja a altura média que eles terão, se possível.

Jordan H
fonte
3
Isso é legal se funcionar, mas os documentos não mencionam isso, e nem a sessão WWDC, se bem me lembro. Os documentos para UITableViewAutomaticDimensiondizer "se você retornar esta constante em tableView:heightForHeaderInSection:ou tableView:heightForFooterInSection:, UITableViewusa uma altura que se ajusta ao valor retornado de tableView:titleForHeaderInSection:ou tableView:titleForFooterInSection:(se o título não for nil)."
Aaron Brager
28
Isso não funcionou para mim. Meu cabeçalho de seção foi capaz de calcular a altura automaticamente, mas sobrepõe as células da seção. Estou configurando minha visualização de cabeçalho usando um arquivo xib e configurando minhas restrições no construtor de interface. Esse é o meu problema? Onde vocês estão criando as restrições? Obrigado!
CoBrA2168
5
Conforme prometido, aqui está o código de amostra: github.com/ebetabox/DynamicCellSectionHeight
PakitoV
10
Outro ponto importante aqui, as células da sua tabela também precisam ser configuradas para cálculo automático de altura (UITableViewAutomaticDimension) para que funcione nas seções.
Bob Spryn
9
Você deve ter estimatedSectionHeaderHeightou tableView:estimatedHeightForHeaderInSection:AND sectionHeaderHeightou tableView:heightForHeaderInSection:. Além disso, se estiver usando os métodos de delegado, você deve retornar um valor maior que 1,00 para a estimativa (comportamento completamente não documentado), caso contrário, o delegado para altura NÃO será chamado e a altura do cabeçalho de exibição de tabela padrão será usada.
Vadoff
29

Isso pode ser feito definindo (ou retornando) a estimatedSectionHeaderHeightvisualização na sua mesa.

Se o cabeçalho da seção estiver sobrepondo as células após a configuraçãoestimatedSectionHeaderHeight , certifique-se de usar um estimatedRowHeighttambém.

(Estou adicionando esta resposta porque o segundo parágrafo contém uma resposta para um problema que pode ser encontrado depois de ler todos os comentários que alguns podem ignorar.)

Clay Ellis
fonte
1
Obrigado, depois de definir estimatedRowHeightisso funciona como um charme :)
sz ashik
1
Isso é verdadeiro mesmo se você NÃO estiver usando UITableViewAutomaticDimension para linhas. Obrigado por me economizar uma hora.
Ryan Romanchuk de
14

Fiquei preso no mesmo problema em que a plataforma estava obtendo altura zero até e a menos que eu forneça uma altura fixa no delegado para heighForHeaderInSection .

Tentei várias soluções, que incluem

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

Mas nada funcionou. Meu celular também estava usando autolayouts adequados. As linhas estavam mudando sua altura dinamicamente usando o código a seguir, mas o cabeçalho da seção não.

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

A correção é extremamente simples e estranha também, mas eu tive que implementar os métodos delegados em vez de um código de linha para o estimatedSectionHeaderHeighte sectionHeaderHeightque funciona da seguinte maneira para o meu caso.

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

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

Swift 4+

trabalhando (testado 100%)

Se você precisar de seção e linha com altura dinâmica baseada no conteúdo, poderá usar o código abaixo:

Em viewDidLoad () escreva estas linhas:

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

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

Agora definimos a altura da linha e a altura da seção usando os métodos UITableView Delegate:

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

       return UITableView.automaticDimension

   }
Sr.Javed Multani
fonte
NOTA para esta ótima resposta. A partir de 2020 , parecia ok usar SOMENTE as quatro propriedades em viewDidLoad.
Fattie
NOTA para esta ótima resposta. A partir de 2020, você precisa das duas linhas "inúteis" que dão uma altura estimada (digamos, 20 ou mais).
Fattie
6

eu tentei

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

mas não dimensionou corretamente o cabeçalho com rótulo multilinha. Adicionei isso para resolver meu problema:

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

    // Recalculates height
    tableView.beginUpdates()
    tableView.endUpdates()
}
iuriimoz
fonte
defina as funções da fonte de dados tableView:estimatedHeightForHeaderInSectione em tableView:heightForHeaderInSectionvez de definir em viewDidLoad.
Keith Yeoh
Descobri que a configuração estimatedSectionHeaderHeightsó é necessária abaixo do iOS 11
doctorBroctor
1

No meu caso:

  1. definido programaticamente não funciona .

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension.

  1. definido no storyboard não funciona .

  2. substituir heightForHeaderInSection funcionou .

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

ambiente de teste:

  • Mac OS 10.13.4
  • XCode Versão 9.4.1
  • Simulador iPhone 8 Plus
Codus
fonte
0

Sim, funciona para mim. Tenho que fazer mais alterações conforme abaixo:

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

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

    return label
}
arg_vn
fonte
-2

Eu modifiquei iuriimoz resposta . Acabou de substituir o método viewWillAppear:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 25


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

    // Recalculates height
    tableView.layoutIfNeeded() 
}

Adicione também tableView.layoutIfNeeded () ao

override func viewDidAppear(_ animated: Bool) {

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

Para iOS 10

tableView.beginUpdates()
tableView.endUpdates()

tem efeito de animação "fade" em viewWillAppear para mim

Irina
fonte