Uma de nossas telas de aplicativos exige que você coloque um UICollectionView
dentro de um UITableViewCell
. Isso UICollectionView
terá um número dinâmico de itens, resultando em uma altura que também deve ser calculada dinamicamente. No entanto, estou com problemas para tentar calcular a altura do incorporado UICollectionView
.
Nossa abrangência UIViewController
foi criada no Storyboards e utiliza o layout automático. Mas, eu não sei como aumentar dinamicamente a altura do com UITableViewCell
base na altura do UICollectionView
.
Alguém pode dar algumas dicas ou conselhos sobre como fazer isso?
ios
uitableview
uicollectionview
Homem sombra
fonte
fonte
UITableViewCell
diferente da sua exibição de tablatura acutal? Você precisa de rolagem vertical em ambos osUICollectionView
eUITableView
Respostas:
A resposta certa é SIM , você pode fazer isso.
Me deparei com esse problema há algumas semanas. Na verdade, é mais fácil do que você imagina. Coloque suas células em NIBs (ou storyboards) e fixe-as para permitir que o layout automático faça todo o trabalho
Dada a seguinte estrutura:
A solução é instruir o layout automático a calcular primeiro os tamanhos de collectionViewCell, depois a coleção visualizar contentSize e usá-lo como o tamanho da sua célula. Este é o método UIView que "faz a mágica":
Você deve definir aqui o tamanho do TableViewCell, que no seu caso é o contentSize do CollectionView.
CollectionViewCell
No CollectionViewCell, você deve informar a célula para fazer o layout toda vez que alterar o modelo (por exemplo: você define um UILabel com um texto e, em seguida, a célula precisa ser layout novamente).
TableViewCell
O TableViewCell faz a mágica. Ele possui uma saída para o seu collectionView, habilita o layout automático para as células collectionView usando o estimadoItemSize do UICollectionViewFlowLayout .
Em seguida, o truque é definir o tamanho da célula tableView no método systemLayoutSizeFittingSize .... (NOTA: iOS8 ou posterior)
NOTA: Tentei usar o método de altura da célula delegada do tableView.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
Mas é tarde demais para o sistema de layout automático calcular o contentSize CollectionView e, às vezes, você pode encontrar células redimensionadas incorretas.TableViewController
Lembre-se de ativar o sistema de layout automático para as células tableView no seu TableViewController :
CRÉDITO: @rbarbera ajudou a resolver isso
fonte
cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);
"Simulará" uma célula longa com um collectionView longo, para que o collectionView calcule o tamanho de todas as suas células. Caso contrário, o collectionView calculou apenas os tamanhos visíveis das células e definiu incorretamente a altura do talbeViewCell.systemLayoutSizeFittingSize
, eu encontrei um problema rapidamente ao recarregar a célula, os aplicativos parecem estar presos após oself.collectionView.layoutIfNeeded()
. Eu o corrigi definindo a altura do quadro com 1 em vez da altura máxima. Espero que ajude se alguém tropeçar neste problema.systemLayoutSizeFitting
, inverter a ordem do que é mostrado na resposta atualmente, de modo que as primeirascollectionView.layoutIfNeeded()
corridas, entãocollectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
Acho que minha solução é muito mais simples do que a proposta por @PabloRomeu.
Etapa 1. Crie uma saída de
UICollectionView
paraUITableViewCell subclass
, ondeUICollectionView
é colocado. Vamos, seu nome serácollectionView
Etapa 2. Adicione o IB para
UICollectionView
restrição de altura e crie saídaUITableViewCell subclass
também. Vamos, o nome serácollectionViewHeight
.Etapa 3. Em
tableView:cellForRowAtIndexPath:
adicionar código:fonte
collectionView
todos os ladosUITableViewCell
e definotableView.estimatedRowHeight = 44;
etableView.rowHeight = UITableViewAutomaticDimension;
As visualizações de tabela e de coleção são
UIScrollView
subclasses e, portanto, não gostam de ser incorporadas a outra visualização de rolagem, enquanto tentam calcular o tamanho do conteúdo, reutilizar células etc.Eu recomendo que você use apenas uma exibição de coleção para todos os seus objetivos.
Você pode dividi-lo em seções e "tratar" o layout de algumas seções como uma exibição de tabela e outras como uma exibição de coleção. Afinal, não há nada que você não possa alcançar com uma exibição de coleção que você pode com uma exibição de tabela.
Se você tiver um layout de grade básico para as "partes" da exibição da coleção, também poderá usar células de tabela regulares para manipulá-las. Ainda assim, se você não precisar do suporte ao iOS 5, use melhor as visualizações de coleção.
fonte
layoutAttributesForItemAtIndexPath
diferentes seções da minha subclasse personalizada deUICollectionViewLayout
?A resposta de Pablo Romeu acima ( https://stackoverflow.com/a/33364092/2704206 ) me ajudou imensamente com meu problema. No entanto, tive que fazer algumas coisas de maneira diferente para que isso funcionasse para o meu problema. Primeiro, eu não precisava ligar com tanta
layoutIfNeeded()
frequência. Eu só tinha que chamá-lo nacollectionView
nasystemLayoutSizeFitting
função.Em segundo lugar, eu tinha restrições de layout automático em minha exibição de coleção na célula de exibição de tabela para fornecer algum preenchimento. Então eu tive que subtrair as margens inicial e final do
targetSize.width
quando definir acollectionView.frame
largura do. Eu também tive que adicionar as margens superior e inferior àCGSize
altura do valor de retorno .Para obter essas constantes de restrição, tive a opção de criar saídas para as restrições, codificar permanentemente suas constantes ou procurá-las por um identificador. Decidi optar pela terceira opção para tornar minha classe de célula de exibição de tabela personalizada facilmente reutilizável. No final, era tudo o que eu precisava para fazer funcionar:
Como função auxiliar para recuperar uma restrição por identificador, adiciono a seguinte extensão:
NOTA: Você precisará definir o identificador nessas restrições no seu storyboard ou em qualquer lugar em que elas estejam sendo criadas. A menos que eles tenham uma constante 0, isso não importa. Além disso, como na resposta de Pablo, você precisará usar
UICollectionViewFlowLayout
como o layout da sua exibição de coleção. Por fim, certifique-se de vincular ocollectionView
IBOutlet ao seu storyboard.Com a célula de exibição de tabela personalizado acima, agora eu posso subclasse-lo em qualquer outra célula exibição de tabela que precisa de uma visão de coleção e tê-lo implementar o
UICollectionViewDelegateFlowLayout
eUICollectionViewDataSource
protocolos. Espero que isso seja útil para outra pessoa!fonte
Eu li todas as respostas. Isso parece servir a todos os casos.
fonte
Uma alternativa à solução de Pablo Romeu é personalizar o próprio UICollectionView, em vez de fazer o trabalho na célula de exibição de tabela.
O problema subjacente é que, por padrão, uma exibição de coleção não possui tamanho intrínseco e, portanto, não pode informar o layout automático das dimensões a serem usadas. Você pode remediar isso criando uma subclasse personalizada que retorne um tamanho intrínseco útil.
Crie uma subclasse de UICollectionView e substitua os seguintes métodos
(Você também deve substituir os métodos relacionados: reloadSections, reloadItemsAtIndexPaths de maneira semelhante a reloadData ())
A chamada layoutIfNeeded força a exibição da coleção a recalcular o tamanho do conteúdo, que pode ser usado como o novo tamanho intrínseco.
Além disso, você precisa lidar explicitamente com as alterações no tamanho da visualização (por exemplo, na rotação do dispositivo) no controlador de visualização de tabela
fonte
Eu estava enfrentando o mesmo problema recentemente e quase tentei todas as soluções nas respostas, algumas delas funcionaram e outras não minha principal preocupação com a abordagem @PabloRomeu é que, se você tiver outro conteúdo na célula (além da exibição de coleção) você precisará calcular as alturas e as alturas de suas restrições e retornar o resultado para obter o layout automático e não gosto de calcular as coisas manualmente no meu código. Então, aqui está a solução que funcionou bem para mim sem fazer nenhum cálculo manual no meu código.
na
cellForRow:atIndexPath
exibição de tabela, faço o seguinte:Acho que o que acontece aqui é forçar a célula tableview a ajustar sua altura após o cálculo da altura da exibição de coleção. (depois de fornecer a data collectionView à fonte de dados)
fonte
Eu colocaria um método estático na classe de exibição de coleção que retornará um tamanho com base no conteúdo que ela terá. Em seguida, use esse método no
heightForRowAtIndexPath
para retornar o tamanho adequado.Observe também que você pode ter um comportamento estranho ao incorporar esses tipos de viewControllers. Eu fiz isso uma vez e tive alguns problemas estranhos de memória que nunca resolvi.
fonte
Talvez minha variante seja útil; Estive decidindo esta tarefa nas últimas duas horas. Não pretendo que seja 100% correto ou ideal, mas minha habilidade ainda é muito pequena e gostaria de ouvir comentários de especialistas. Obrigado. Uma observação importante: isso funciona para a tabela estática - é especificada pelo meu trabalho atual. Então, tudo que eu uso é viewWillLayoutSubviews de tableView . E um pouco mais.
fonte
Abordagem mais fácil que eu criei até agora, Créditos para a resposta @igor acima,
Na sua classe tableviewcell, insira este
e, é claro, altere ooutletviewoutlet com sua tomada na classe da célula
fonte
Recebo uma ideia do @Igor post e investi meu tempo nisso para o meu projeto com rapidez
Apenas passe isso no seu
Adição: se o UICollectionView aparecer instável ao carregar as células.
fonte
A solução de Pablo não funcionou muito bem para mim, tive efeitos visuais estranhos (o collectionView não está se ajustando corretamente).
O que funcionou foi ajustar a restrição de altura do collectionView (como um NSLayoutConstraint) para o collectionView contentSize durante
layoutSubviews()
. Esse é o método chamado quando o autolayout é aplicado à célula.fonte
No seu UITableViewDelegate:
Substitua itemCount e CollectionViewCellHeight pelos valores reais. Se você tiver uma matriz de matrizes, itemCount pode ser:
Como queiras.
fonte
collectionViewCellHeight
antes de renderizar.1.Criar célula fictícia.
2. Use o método collectionViewContentSize em UICollectionViewLayout de UICollectionView usando dados atuais.
fonte
Você pode calcular a altura da coleção com base em suas propriedades, como
itemSize
,sectionInset
,minimumLineSpacing
,minimumInteritemSpacing
, se o seucollectionViewCell
tem a borda de uma regra.fonte