redimensionar superview após as subviews mudarem dinamicamente usando autolayout

83

Não consigo, pelo amor de Deus, o jeito desse superview de redimensionamento.

Eu tenho um UIView *superview com 4 UILabels. 2 funcionam como cabeçalho para os outros 2.

O conteúdo em todos os 4 é dinâmico vindo do banco de dados.

SizeToFitvs SizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, passando UILayoutFittingCompressedSizeou UILayoutFittingExpandedSize.

Eu uso o autolayout programaticamente e configurei a altura do superview para ser igual ou maior a um número fictício.

onde e como eu uso esses SizeToFitvs sizeThatFits:(CGSize)vs UIView systemLayoutSizeFittingSize:, passando UILayoutFittingCompressedSizeou UILayoutFittingExpandedSize. Eu li muitas dicas aqui na pilha, mas acabei sem nada.

Preciso recalcular as restrições para o superview em algum lugar específico. Maby definindo a altura como ´ @propriedade` em sua classe de controlador e removendo e lendo? Atm, tentei colocar tudo em todos os lugares e mais alguns. Ainda assim, obtenho o resultado final do mesmo tamanho com a altura fictícia e o texto flutuando do lado de fora. Mesmo depois de definir clipsToBound em subview.

Estou coçando meu cabelo de .. ajuda

Pedroinpeace
fonte
1
Ei, você poderia postar seu código em algum lugar no pastebin ou algo assim se eu pudesse dar uma olhada? Estou sofrendo de um problema semelhante. Já se passou uma semana ou mais.
esh

Respostas:

104

Se você estiver usando Auto Layout, faça o seguinte:

  1. Certifique-se de não adicionar restrições de largura e / ou altura fixas a qualquer uma de suas subvisualizações (dependendo de quais dimensões você deseja dimensionar dinamicamente). A ideia é deixar o tamanho do conteúdo intrínseco de cada subvisualização determinar a altura da subvisualização. UILabels vêm com 4 restrições implícitas automáticas que irão (com prioridade menor que a necessária) tentar manter o quadro do rótulo no tamanho exato necessário para caber todo o texto dentro.

  2. Certifique-se de que as bordas de cada etiqueta estejam conectadas rigidamente (com restrições de prioridade obrigatórias) às bordas umas das outras e à sua visão panorâmica. Você quer ter certeza de que, se imaginar um dos rótulos crescendo em tamanho, isso forçaria os outros rótulos a abrirem espaço para ele e, o mais importante, forçaria a visão geral a se expandir também.

  3. Apenas adicione restrições à supervisão para definir sua posição, não o tamanho (pelo menos, não para as dimensões que você deseja dimensionar dinamicamente). Lembre-se de que se você configurar as restrições internas corretamente, seu tamanho será determinado pelos tamanhos de todas as subvisualizações, uma vez que suas arestas estão conectadas às suas de alguma forma.

É isso aí. Você não precisa ligar sizeToFitou systemLayoutSizeFittingSize:fazer isso funcionar, apenas carregue suas visualizações e configure o texto e pronto. O mecanismo de layout do sistema fará os cálculos para você resolver suas restrições. (Se houver alguma coisa, talvez você precise chamar setNeedsLayouto superview ... mas isso não deve ser necessário).

smileyborg
fonte
Obrigado smileyborg. Uma resposta tardia, pois eu estava no meio de um projeto e não entendi muito bem o que você disse. Agora eu tive a chance de trabalhar um pouco mais com restrições em programaticamente e especialmente com constraintsWithVisualFormate entendi totalmente o que você quis dizer sobre conter subviews esticando e empurrando o superview para seu tamanho :) Obrigado novamente
Pedroinpeace
Eu concordo com a solução, mas não está funcionando para mim, verifique stackoverflow.com/questions/34635838/…
Omer
Essa resposta é mágica. Muito menos esforço da minha parte para que as vistas pareçam boas.
Chris de
1
Deve ser mencionado que você deve definir translatesAutoresizingMaskIntoConstraints = NOse estiver usando o xib.
KudoCC
translatesAutoresizingMaskIntoConstraints = NO é a resposta para o meu caso. Mas agora a visualização do container perdeu frame e sua origem é sempre (0,0), não posso colocá-la no lugar que desejo. stackoverflow.com/questions/45548372/…
karim
24

Usar visualizações de contêiner

No exemplo a seguir, tenho uma imagem de 30x30 e UILabelé menor do que a visualização que contém o texto do espaço reservado. Eu precisava que a visualização de conteúdo fosse pelo menos tão grande quanto a imagem, mas precisava crescer para conter texto de várias linhas.

No formato visual, o contêiner interno se parece com isto:

H:|-(15.0)-[image(30.0)]-(15.0)-[label]-(15.0)-|
V:|[image(30.0)]|
V:|[label(>=30.0)]|

Em seguida, defina a visualização de conteúdo para corresponder à altura do rótulo. Agora, a visualização contida terá o tamanho do rótulo.

Como @smileyborg apontou em sua resposta, conectar o conteúdo rigidamente ao superview informa ao mecanismo de layout que a visualização do contêiner simples deve fazer com que ele cresça.

Retângulos de alinhamento amarelos

Se você quiser os retângulos de alinhamento amarelos, adicione -UIViewShowAlignmentRects YESna lista de argumentos de execução do seu esquema.

UILabel que é multilinha

Cameron Lowell Palmer
fonte
12
-UIViewShowAlignmentRects YES- ótima dica!
Ralfonso
2
Neste caso, o recipiente deve apenas adequar sua altura ao rótulo. E se o contêiner se adaptar à soma das alturas de mais de uma visualização?
da Rocha Pires
7

Isso ficou muito mais fácil com a introdução de Stack Views no iOS 9. Use uma stack view dentro de sua view para conter todo o seu conteúdo que é redimensionado e, em seguida, basta chamar

view.setNeedsUpdateConstraints()
view.updateConstraintsIfNeeded()
view.setNeedsLayout()
view.layoutIfNeeded()

depois de alterar seu conteúdo. Então você pode obter seu novo tamanho ligando

view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

se você precisar calcular o tamanho exato necessário para uma visualização.

Jacob Ruth
fonte
2
Estou usando o StackView e adicionando visualizações dinamicamente, essas visualizações não estão sendo redimensionadas. @ JacobRuth
Mansuu ....
6

Isso quase segue a resposta de @smileyborg e vem com um exemplo concreto.

insira a descrição da imagem aqui

Não descreve todas as restrições, exceto aquelas relacionadas ao cálculo da altura dos objetos de IU.

  1. [Rótulo] Os rótulos não devem ter uma heightrestrição fixa , neste caso, o AutoLayout não redimensionará os rótulos para caber no texto, portanto, definir as restrições de borda é a chave. (setas verdes)
  2. [Subview] As etapas 1 e 3 são muito fáceis de seguir, mas esta etapa pode ser mal interpretada. Como no caso dos rótulos, as subvisualizações não devem ter uma heightrestrição definida. Todas as subvisualizações devem ter uma toprestrição definida, ignorando a bottomrestrição, o que pode fazer você pensar que irá disparar uma exceção de restrição não satisfeita no tempo de execução, mas não irá se você definir a bottomrestrição para a última subvisualização. Deixar de fazer isso vai estragar o layout. (Setas vermelhas)

  3. [Superview] Defina todas as restrições da maneira que você precisa, mas preste muita atenção às heightrestrições. Atribua a ele um valor aleatório, mas torne-o opcional, o AutoLayout definirá a altura exatamente para caber nas subvisualizações. (setas azuis)

Isso funciona perfeitamente, não há necessidade de chamar nenhum método adicional de atualização do layout do sistema.

Stefan
fonte
como tornar a altura opcional .. Sou novo no iOS, então não consigo descobrir. Obrigado
Faisal Naseer