Desde que descobri AutoLayout
que o uso em todos os lugares, agora estou tentando usá-lo com umtableHeaderView
.
Eu fiz uma subclass
de UIView
tudo adicionado (etiquetas etc ...) eu queria com suas limitações, então eu adicionei este CustomView
ao UITableView
'tableHeaderView
.
Tudo funciona bem, exceto o UITableView
sempre exibido acima do CustomView
, acima, quero dizer que CustomView
está abaixo doUITableView
por isso não pode ser visto!
Parece que não importa o que eu faça, o height
de UITableView
' tableHeaderView
é sempre 0 (assim como a largura, x e y).
Minha pergunta: é possível fazer isso sem definir o quadro manualmente ?
EDIT:
O CustomView
' subview
que estou usando tem estas restrições:
_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];
Estou usando uma biblioteca útil 'KeepLayout' porque escrever restrições manualmente leva uma eternidade e muitas linhas para uma única restrição, mas os métodos são autoexplicativos.
E o UITableView
tem estas restrições:
_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];
_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;
Não sei se tenho que definir algumas restrições diretamente no CustomView
, acho que a altura do CustomView é determinada pelas restrições no UILabel
"título" nele.
EDIT 2: Após outra investigação, parece que a altura e a largura do CustomView estão calculadas corretamente, mas o topo do CustomView ainda está no mesmo nível que o topo do UITableView e eles se movem juntos quando eu rolar.
fonte
Respostas:
Eu perguntei e respondi uma pergunta semelhante aqui . Em resumo, adiciono o cabeçalho uma vez e o utilizo para encontrar a altura necessária. Essa altura pode então ser aplicada ao cabeçalho, e o cabeçalho é definido uma segunda vez para refletir a alteração.
Se você tiver rótulos com várias linhas, isso também depende da configuração da visualização personalizada de preferredMaxLayoutWidth de cada rótulo:
ou talvez de forma mais geral:
Atualização de janeiro de 2015
Infelizmente, isso ainda parece necessário. Aqui está uma versão rápida do processo de layout:
Achei útil mover isso para uma extensão no UITableView:
Uso:
fonte
preferredMaxLayoutWidth
é adicionar uma restrição de largura (igual à largura da visualização da tabela) na visualização do cabeçalho antes de usarsystemLayoutSizeFittingSize:
.self.tableView.tableHeaderView
let height = header.systemLayoutSizeFittingSize(CGSizeMake(CGRectGetWidth(self.bounds), 0), withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel).height
header.setNeedsLayout() header.layoutIfNeeded() header.frame.size = header.systemLayoutSizeFitting(UILayoutFittingCompressedSize) self.tableHeaderView = header
funcionaria no iOS 10.2Não consegui adicionar uma visualização de cabeçalho usando restrições (no código). Se eu atribuir à minha visualização uma restrição de largura e / ou altura, recebo uma falha com a mensagem que diz:
Quando adiciono uma visualização no storyboard à minha visualização de tabela, ela não mostra restrições e funciona bem como uma visualização de cabeçalho, então acho que o posicionamento da visualização de cabeçalho não é feito usando restrições. Não parece se comportar como uma visão normal a esse respeito.
A largura é automaticamente a largura da visualização da mesa, a única coisa que você precisa definir é a altura - os valores de origem são ignorados, então não importa o que você coloque para eles. Por exemplo, funcionou bem (assim como 0,0,0,80 para o reto):
fonte
translatesAutoresizingMaskIntoConstraints = NO
. Ativar a tradução evita o erro - suspeito que aUITableView
partir do 7.1 não tenta fazer o layout automático de sua exibição de cabeçalho e deseja algo com o quadro predefinido.Eu vi muitos métodos aqui fazendo muitas coisas desnecessárias, mas você não precisa de muito para usar o layout automático na visualização do cabeçalho. Você só precisa criar seu arquivo xib, colocar suas restrições e instanciá-lo assim:
fonte
Outra solução é despachar a criação da visualização do cabeçalho para a próxima chamada de thread principal:
Nota: corrige o bug quando a visualização carregada tem uma altura fixa. Não tentei quando a altura do cabeçalho depende apenas de seu conteúdo.
EDITAR:
Você pode encontrar uma solução mais limpa para este problema implementando esta função e chamando-a em
viewDidLayoutSubviews
fonte
tableHeaderView
são meio bugs com autolayout. Existem algumas soluções alternativas, como esta. Mas desde que eu escrevi isso, eu encontrei uma solução melhor e mais limpo aqui stackoverflow.com/a/21099430/127493 chamando seu- (void)sizeHeaderToFit
noviewDidLayoutSubviews
Código:
fonte
Esta solução estendida http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/ para visualização do rodapé da tabela:
fonte
self.tableFooterView.transform
parte? Por que isso é necessário?Você pode obter o autolayout para fornecer um tamanho usando o método systemLayoutSizeFittingSize .
Você pode então usar isso para criar o quadro de seu aplicativo. Essa técnica funciona sempre que você precisa saber o tamanho de uma visualização que usa autolayout internamente.
O código em swift parece
Ou em Objective-C
Também deve ser observado que, nesta instância específica, substituir o requireConstraintBasedLayout em sua subclasse, resulta em uma passagem de layout sendo executada; no entanto, os resultados dessa passagem de layout são ignorados e o quadro do sistema definido para a largura de tableView e altura 0.
fonte
O seguinte funcionou para mim.
UIView
como a visualização do cabeçalho.UIView
O principal benefício que vejo é limitar os cálculos do quadro. A Apple realmente deveria atualizar
UITableView
a API para tornar isso mais fácil.Exemplo de uso do SnapKit:
fonte
Coisas estranhas acontecem. systemLayoutSizeFittingSize funciona muito bem para iOS9, mas não para iOS 8 no meu caso. Portanto, esse problema é resolvido com bastante facilidade. Basta obter o link para a visualização inferior no cabeçalho e em viewDidLayoutSubviews após a super chamada atualizar os limites da visualização do cabeçalho inserindo a altura como CGRectGetMaxY (yourview.frame) + preenchimento
UPD: A solução mais fácil de todas : Então, na visualização do cabeçalho, coloque a subvisualização e fixe-a à esquerda , direita , topo . Nessa subvisualização, coloque suas subvisualizações com restrições de altura automática. Depois disso, dê todo o trabalho para o autolayout (nenhum cálculo necessário)
Como resultado, a subvisualização está se expandindo / diminuindo como deveria, no final ela chama viewDidLayoutSubviews. No momento, sabemos o tamanho real da visualização, então defina headerView height e atualize-a reatribuindo. Funciona como um encanto!
Também funciona para visualização de rodapé.
fonte
Atualizado para Swift 4.2
fonte
você pode adicionar restrição de localização superior + horizontal entre o cabeçalho e tableview, para colocá-lo, corretamente (se o próprio cabeçalho contiver todas as restrições de layout internas necessárias para ter um quadro correto)
no método tableViewController viewDidLoad
fonte
Minha visualização do cabeçalho da tabela é uma subclasse UIView - eu criei um único UIView contentView dentro do inicializador, com seus limites iguais aos do quadro da visualização do cabeçalho da tabela e adicionei todos os meus objetos como uma subvisão desse.
Em seguida, adicione as restrições para seus objetos dentro do
layoutSubviews
método da visualização do cabeçalho da tabela em vez de dentro do inicializador. Isso resolveu o acidente.fonte
Meu AutoLayout está funcionando muito bem:
fonte
Na maioria dos casos, a melhor solução é simplesmente não lutar contra a estrutura e adotar máscaras de redimensionamento automático:
Ao usar máscaras de redimensionamento automático, você informa ao framework como sua visualização deve mudar de tamanho quando a visualização muda de tamanho. Mas essa mudança é baseada no quadro inicial que você definiu.
fonte
Eu sei que este é um post antigo, mas depois de passar por todos os posts do SO sobre isso e passar uma tarde inteira brincando com isso, eu finalmente encontrei uma solução limpa e muito simples
Em primeiro lugar, minha hierarquia de visualização é assim:
tableHeaderView
Agora dentro da View (No.3), eu configurei todas as restrições como faria normalmente, incluindo o espaço inferior do container. Isso fará com que o contêiner (ou seja, 3.View, ou seja, headerView), se dimensione com base em suas subvisualizações e suas restrições.
Depois disso, eu defino as restrições entre
3. View
e2. View
para estas:Observe que eu omito intencionalmente o espaço inferior intencionalmente.
Depois que tudo isso é feito no storyboard, tudo o que resta fazer é colar essas três linhas de códigos:
fonte
Dicas: Se você usar o método setAndLayoutTableHeaderView, deverá atualizar o quadro de subvisualizações, portanto, nesta situação, o UILabel's preferredMaxLayoutWidth deve chamar antes de systemLayoutSizeFittingSize ser chamado, não chame em layoutSubview.
show de código
fonte
Compartilhe minha abordagem.
UITableView+XXXAdditions.m
Uso.
fonte
No meu caso, o método com systemLayoutSizeFittingSize por algum motivo não funcionou. O que funcionou para mim foi uma modificação da solução postada pelo HotJard (a solução original também não funcionou no meu caso no iOS 8). O que eu precisava fazer é, na visualização do cabeçalho, colocar uma subvisualização e fixá-la à esquerda, direita, parte superior (não fixe na parte inferior). Coloque tudo usando autolayout nessa subvisão e no código faça o seguinte:
fonte
Um post antigo. Mas um bom post. Aqui estão meus 2 centavos.
Em primeiro lugar, certifique-se de que sua visualização de cabeçalho tenha suas restrições organizadas de forma que possa suportar seu próprio tamanho de conteúdo intrínseco. Em seguida, faça o seguinte.
fonte
Consegui consegui-lo com a seguinte abordagem (isso funciona para o rodapé da mesma maneira).
Primeiro, você precisará de uma pequena
UITableView
extensão:Swift 3
Em sua implementação de classe de controlador de visualização:
Observações sobre a
UIView
implementação da subvisão de um cabeçalho :Você deve ter 100% de certeza de que a visualização do cabeçalho possui a configuração correta de layout automático. Eu recomendaria começar com uma visualização de cabeçalho simples com apenas uma restrição de altura e experimentar a configuração acima.
Substituir
requiresConstraintBasedLayout
e retornartrue
:.
fonte
Para usuários Xamarin:
Supondo que você nomeou a visualização do cabeçalho de sua tableview como TableviewHeader
fonte
Aqui está como você pode fazer em seu
UIViewController
fonte
Qualquer restrição baseada em
UIView
pode ser uma boatableHeaderView
.É necessário definir um
tableFooterView
antes e, em seguida, impor uma restrição adicional à direitatableFooterView
etableHeaderView
.}
Todos os detalhes e trechos de código podem ser encontrados aqui
fonte
Eu descobri uma solução alternativa. envolva sua visão de cabeçalho autolayout wrriten xib em um wrapper uiview vazio e atribua a visão de cabeçalho à propriedade tableViewHeader de tableView.
fonte
Aqui está o que funciona para UITableViewController no ios 12,
Arraste um UIView no TableView acima de todas as células de protótipo para cabeçalho e abaixo de todas as células de protótipo para rodapé. Configure seu cabeçalho e rodapé conforme necessário. Defina todas as restrições necessárias.
Agora use os seguintes métodos de extensão
e chamá-lo em ViewDidLayoutSubviews da subclasse de UITableViewController
fonte
Eu encontrei o problema de obter largura de 375pt, a única maneira que funcionou para mim é retransmitir o tableView para obter a largura correta. Eu também preferi o AutoLayout em vez de definir o tamanho do quadro.
Esta é a versão que funciona para mim:
Xamarin.iOS
Versão Swift (modificada da resposta @Ben Packard)
fonte
Eu criei uma subclasse de
UITableView
e useiUIStackView
para cabeçalho e rodapé, também permite definir mais de uma visualização.https://github.com/omaralbeik/StackableTableView
fonte
Minha solução é fazer uma nova classe como essa.
Para usá-lo, basta adicionar todas as suas subvisualizações a uma instância de
BaseTableHeaderView
e anexá-las à sua visão de tabela.Ele será redimensionado automaticamente com base em suas restrições.
fonte
A resposta aceita é útil apenas para tabelas com uma única seção. Para várias seções,
UITableView
certifique-se de que seu cabeçalho herda deUITableViewHeaderFooterView
e você ficará bem.Como alternativa, basta incorporar seu cabeçalho atual no
contentView
de aUITableViewHeaderFooterView
. Exatamente comoUITableViewCell
funciona.fonte
tableHeaderView
não é sobre o cabeçalho da seção.