UITableView
definido para células estáticas.
É possível ocultar algumas das células programaticamente?
ios
objective-c
uitableview
Shmidt
fonte
fonte
IBOutletCollection
mas não vejo como isso faria diferença. Eu só baixei o código ontem, então não acho que seja uma versão antiga.Para ocultar células estáticas no UITable:
Na classe delegada do controlador UITableView:
Objetivo-C:
Rápido:
Este método será chamado para cada célula na UITable. Depois que a chama para a célula que você deseja ocultar, definimos sua altura como 0. Identificamos a célula de destino criando uma saída para ela:
fonte
ClipToBounds
problema, você também pode definir a célula como oculta. Isso me pareceria mais limpo. ;-)A melhor maneira é descrita no seguinte blog http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
fonte
Minha solução segue uma direção semelhante à de Gareth, embora eu faça algumas coisas de maneira diferente.
Aqui vai:
1. Esconda as células
Não há como ocultar diretamente as células.
UITableViewController
é a fonte de dados que fornece as células estáticas e, atualmente, não há como dizer "não forneça a célula x". Portanto, precisamos fornecer nossa própria fonte de dados, que delega para aUITableViewController
fim de obter as células estáticas.O mais fácil é subclassificar
UITableViewController
e substituir todos os métodos que precisam se comportar de maneira diferente ao ocultar células .No caso mais simples (tabela de seção única, todas as células têm a mesma altura), isso seria assim:
Se sua tabela tiver várias seções ou as células tiverem alturas diferentes, será necessário substituir mais métodos. O mesmo princípio se aplica aqui: você precisa compensar indexPath, seção e linha antes de delegar para super.
Lembre-se também de que o parâmetro indexPath para métodos como
didSelectRowAtIndexPath:
será diferente para a mesma célula, dependendo do estado (ou seja, o número de células ocultas). Portanto, é provavelmente uma boa ideia sempre compensar qualquer parâmetro indexPath e trabalhar com esses valores.2. Animar a mudança
Como Gareth já afirmou, você obtém grandes falhas se animar alterações usando o
reloadSections:withRowAnimation:
métodoEu descobri que, se você ligar
reloadData:
imediatamente depois, a animação será muito melhorada (apenas pequenas falhas). A tabela é exibida corretamente após a animação.Então, o que estou fazendo é:
fonte
numberOfRowsInSection:
é chamado somente quando a tabela é carregada pela primeira vez. Quando eu chamo [self.tableView reloadData] -numberOfRowsInSection:
nunca é chamado novamente. ApenascellForRowAtIndexPath:
é chamado. o que estou perdendo?cellOneOutlet.hidden = true
agora substitua o método abaixo, verifique qual status da célula está oculto e retorne a altura 0 para essas células. Essa é uma das muitas maneiras pelas quais você pode ocultar qualquer célula no tableView estático rapidamente.
fonte
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
. Presumo que seja substituído porlet tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)
.UITableViewController
, não tenhoUITableView
métodos de delegação. Para que ele seja chamadoheightForRow
, também preciso ter outros métodos?Eu vim com uma alternativa que realmente oculta seções e não as exclui. Tentei a abordagem do @ henning77, mas continuava tendo problemas quando alterava o número de seções do UITableView estático. Esse método funcionou muito bem para mim, mas estou tentando principalmente ocultar seções em vez de linhas. Estou removendo algumas linhas rapidamente, mas é muito mais confuso, então tentei agrupar as coisas em seções que preciso mostrar ou ocultar. Aqui está um exemplo de como estou ocultando seções:
Primeiro declaro uma propriedade NSMutableArray
No viewDidLoad (ou depois de consultar seus dados), você pode adicionar seções que deseja ocultar à matriz.
Em seguida, implemente os seguintes métodos de delegação do TableView
Em seguida, defina a altura do cabeçalho e rodapé como 1 para seções ocultas porque você não pode definir a altura como 0. Isso causa um espaço adicional de 2 pixels, mas podemos compensar isso ajustando a altura do próximo cabeçalho visível.
Em seguida, se você tiver linhas específicas para ocultar, poderá ajustar o numberOfRowsInSection e quais linhas serão retornadas em cellForRowAtIndexPath. Neste exemplo, aqui eu tenho uma seção que possui três linhas em que três podem estar vazias e precisam ser removidas.
Use este offsetIndexPath para calcular o indexPath para linhas nas quais você está removendo condicionalmente as linhas. Não é necessário se você estiver ocultando apenas seções
Existem muitos métodos a serem substituídos, mas o que eu gosto nessa abordagem é que ela é reutilizável. Configure a matriz hiddenSections, adicione-a e ela ocultará as seções corretas. Escondendo as linhas é um pouco mais complicado, mas possível. Não podemos simplesmente definir a altura das linhas que queremos ocultar para 0 se estivermos usando um UITableView agrupado porque as bordas não serão desenhadas corretamente.
fonte
NSMutableSet
emhiddenSections
vez disso. É muito mais rápido, pois você está testando principalmente a associação.NSMutableSet
dehiddenSections
, embora eu entenda que o ponto da sua resposta foi mais conceitual do que exigente quanto ao tipo de estrutura de dados que você deve usar.Acontece que você pode ocultar e mostrar células em um UITableView estático - e com animação. E não é tão difícil de realizar.
Projeto de demonstração
Vídeo do projeto de demonstração
A essência:
Use tableView:heightForRowAtIndexPath:
para especificar alturas de célula dinamicamente com base em algum estado.tableView.beginUpdates();tableView.endUpdates()
tableView.cellForRowAtIndexPath:
dentrotableView:heightForRowAtIndexPath:
. Use indexPaths em cache para diferenciar as células.Mais informações no meu blog (idioma russo)
fonte
Sim, é definitivamente possível, embora eu esteja lutando com o mesmo problema no momento. Consegui fazer com que as células se escondessem e tudo funcionasse bem, mas atualmente não posso fazer a coisa animar perfeitamente. Aqui está o que eu encontrei:
Estou ocultando linhas com base no estado de um botão ON / OFF na primeira linha da primeira seção. Se o interruptor estiver LIGADO, há 1 linha abaixo na mesma seção, caso contrário, existem 2 linhas diferentes.
Eu tenho um seletor chamado quando o comutador é alternado e defino uma variável para indicar em que estado estou. Depois, chamo:
Eu substituo a função tableView: willDisplayCell: forRowAtIndexPath: e se a célula deveria estar oculta, faço isso:
Isso oculta a célula e seu conteúdo, mas não remove o espaço que ocupa.
Para remover o espaço, substitua a função tableView: heightForRowAtIndexPath: e retorne 0 para as linhas que devem estar ocultas.
Você também precisa substituir tableView: numberOfRowsInSection: e retornar o número de linhas nessa seção. Você precisa fazer algo estranho aqui para que, se sua tabela for um estilo agrupado, os cantos arredondados ocorram nas células corretas. Na minha tabela estática, há o conjunto completo de células para a seção; portanto, há a primeira célula que contém a opção, depois uma célula para as opções de estado ON e mais duas células para as opções de estado OFF, um total de 4 células. Quando a opção está ativada, tenho que retornar 4, isso inclui a opção oculta para que a última opção exibida tenha uma caixa arredondada. Quando a opção está desativada, as duas últimas opções não são exibidas, então eu retorno 2. Isso tudo parece desajeitado. Desculpe se isso não está muito claro, é difícil de descrever. Apenas para ilustrar a configuração, esta é a construção da seção da tabela no IB:
Portanto, quando a opção está ativada, a tabela relata duas linhas que são:
Quando a opção está DESLIGADA, a tabela reporta quatro linhas:
Essa abordagem não parece correta por várias razões, é o máximo que eu tenho com a minha experiência até agora; então, deixe-me saber se você encontrar uma maneira melhor. Os problemas que observei até agora são:
Parece errado dizer à tabela que o número de linhas é diferente do que está presumivelmente contido nos dados subjacentes.
Não consigo animar a mudança. Eu tentei usar tableView: reloadSections: withRowAnimation: em vez de reloadData e os resultados não parecem fazer sentido, ainda estou tentando fazer isso funcionar. Atualmente, o que parece acontecer é que o tableView não atualiza as linhas corretas, permanecendo oculto que deve ser exibido e um nulo é deixado na primeira linha. Eu acho que isso pode estar relacionado ao primeiro ponto sobre os dados subjacentes.
Espero que alguém possa sugerir métodos alternativos ou talvez como estender a animação, mas talvez isso o ajude a começar. Minhas desculpas pela falta de hiperlinks para funções, eu os coloquei, mas eles foram rejeitados pelo filtro de spam porque eu sou um usuário relativamente novo.
fonte
[[self tableView] reloadData];
mais uma vez depois de esconder as célulasreturn [super tableView:tableView cellForRowAtIndexPath:indexPath];
naUITableViewController
subclasse para a criação de células estáticas. Caminhos de índice são indexados estático - não dinâmica ...Conforme resposta de Justas, mas para Swift 4:
fonte
tableView.reloadRows(at:, with:)
atualizar as células se você alterar a altura enquanto a linha já estiver visível.Ok, depois de algumas tentativas, tenho uma resposta não comum. Estou usando a variável "isHidden" ou "hidden" para verificar se esta célula deve estar oculta.
crie um IBOutlet para o seu controlador de exibição.
@IBOutlet weak var myCell: UITableViewCell!
Atualize o
myCell
em sua função personalizada, por exemplo, você pode adicioná-lo em viewDidLoad:override func viewDidLoad() { super.viewDidLoad() self.myCell.isHidden = true }
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let cell = super.tableView(tableView, cellForRowAt: indexPath) guard !cell.isHidden else { return 0 } return super.tableView(tableView, heightForRowAt: indexPath) }
Isso reduzirá sua lógica no método delegado, e você só precisará se concentrar nos requisitos de negócios.
fonte
As respostas acima que ocultam / mostram células, alteram rowHeight ou interferem nas restrições de layout automático não funcionaram para mim devido a problemas de layout automático. O código tornou-se intolerável.
Para uma tabela estática simples, o que funcionou melhor para mim foi:
Aqui está um exemplo do meu controlador de exibição de tabela:
fonte
IOS 11 simples e método compatível com IB / Storyboard
Para o iOS 11, descobri que uma versão modificada da resposta de Mohamed Saleh funcionava melhor, com algumas melhorias baseadas na documentação da Apple. Ele é animado, evita hacks feios ou valores codificados e usa alturas de linha já definidas no Interface Builder .
O conceito básico é definir a altura da linha como 0 para todas as linhas ocultas. Em seguida, use
tableView.performBatchUpdates
para acionar uma animação que funcione de forma consistente.Defina as alturas das células
Você quer ter certeza
cellIsHidden
eindexPathOfHiddenCell
está configurado adequadamente para seu caso de uso. Para o meu código, são propriedades no meu controlador de exibição de tabela.Alternando a célula
Seja qual for o método que controla a visibilidade (provavelmente uma ação de botão ou
didSelectRow
), alterne o estado cellIsHidden, dentro de umperformBatchUpdates
bloco:A Apple recomenda
performBatchUpdates
maisbeginUpdates
/endUpdates
sempre que possível.fonte
Encontrei uma solução para animar células ocultas na tabela estática.
Apenas um dicionário adicional é necessário:
E observe a implementação do MyTableViewController. Precisamos de dois métodos para converter indexPath entre índices visíveis e invisíveis ...
Uma alteração da IBAction no valor do UISwitch:
Alguns métodos UITableViewDataSource e UITableViewDelegate:
fonte
Resposta rápida :
Adicione o seguinte método no seu TableViewController:
se o tableView tentar desenhar a célula que você deseja ocultar, ela não será exibida porque sua altura será definida como 0pt, graças ao método acima, todo o resto permanecerá inalterado.
Observe que
indexPathOfCellYouWantToHide
pode ser alterado a qualquer momento :)fonte
No Swift 2.2, eu combinei algumas respostas aqui.
Faça uma saída do storyboard para vincular ao seu staticCell.
Quero ocultar minha primeira célula e defino a altura como 0, conforme descrito acima.
fonte
Swift 4:
fonte
Para o cenário mais fácil ao ocultar células na parte inferior da exibição da tabela, você pode ajustar o contentInset do tableView após ocultar a célula:
fonte
Esta é uma nova maneira de fazer isso usando https://github.com/k06a/ABStaticTableViewController
fonte
A solução do k06a ( https://github.com/k06a/ABStaticTableViewController ) é melhor porque oculta toda a seção, incluindo cabeçalhos e rodapés de células, onde esta solução ( https://github.com/peterpaulis/StaticDataTableViewController ) oculta tudo, exceto o rodapé.
EDITAR
Acabei de encontrar uma solução, se você deseja ocultar o rodapé
StaticDataTableViewController
. É isso que você precisa copiar no arquivo StaticTableViewController.m:fonte
Certamente você pode. Primeiro, retorne ao número do número de células que você deseja exibir no tableView e ligue
super
para obter determinada célula do storyboard e devolva-a para o tableView:Se suas células tiverem hieght diferente, devolva-o também:
fonte
Além da solução @Saleh Masum:
Se você receber erros de layout automático , poderá remover as restrições do
tableViewCell.contentView
Swift 3:
Esta solução depende do fluxo do seu aplicativo . Se você deseja mostrar / ocultar a célula na mesma instância do controlador de exibição, talvez essa não seja a melhor opção, pois remove as restrições .
fonte
Eu tenho uma maneira melhor de ocultar células estáticas e até seções dinamicamente sem hacks.
Definir a altura da linha como 0 pode ocultar uma linha, mas isso não funciona se você deseja ocultar uma seção inteira que conterá alguns espaços, mesmo que você oculte todas as linhas.
Minha abordagem é criar uma matriz de seções de células estáticas. Em seguida, o conteúdo da visualização da tabela será direcionado pela matriz de seção.
Aqui está um código de exemplo:
Dessa forma, você pode reunir todo o seu código de configuração sem precisar escrever o código desagradável para calcular o número de linhas e seções. E, claro, não há
0
mais alturas.Este código também é muito fácil de manter. Por exemplo, se você deseja adicionar / remover mais células ou seções.
Da mesma forma, você pode criar uma matriz de título de cabeçalho de seção e matriz de título de rodapé de seção para configurar seus títulos de seção dinamicamente.
fonte