Não estou falando sobre a propriedade frame, porque a partir dela você só pode obter o tamanho da visualização no xib. Estou falando sobre quando a visualização é redimensionada por causa de suas restrições (talvez após uma rotação ou em resposta a um evento). Existe uma maneira de obter sua largura e altura atuais?
Eu tentei iterar por meio de suas restrições procurando por restrições de largura e altura, mas isso não é muito claro e falha quando há restrições intrínsecas (já que não consigo diferenciar entre as duas). Além disso, isso só funciona se eles realmente tiverem restrições de largura e altura, o que não acontece se dependerem de outras restrições para redimensionar.
Por que isso é tão difícil para mim. ARG!
ios
autolayout
yuf
fonte
fonte
Respostas:
A resposta é
[view layoutIfNeeded]
.Aqui está o porquê:
Você ainda obtém a largura e altura atuais da visualização inspecionando
view.bounds.size.width
eview.bounds.size.height
(ou o quadro, que é equivalente, a menos que você esteja brincando comview.transform
).Se o que você deseja é a largura e a altura implícitas em suas restrições existentes, a resposta não é inspecionar as restrições manualmente, pois isso exigiria que você reimplementasse toda a lógica de resolução de restrições do sistema de layout automático para interpretá-las restrições. Em vez disso, o que você deve fazer é apenas pedir ao layout automático para atualizar esse layout , para que ele resolva as restrições e atualize o valor de view.bounds com a solução correta e, em seguida, inspecione view.bounds.
Como você pede ao layout automático para atualizar o layout? Ligue
[view setNeedsLayout]
se quiser que o layout automático atualize o layout na próxima curva do loop de corrida.No entanto, se você deseja atualizar o layout imediatamente, para que possa acessar imediatamente o novo valor de limites posteriormente em sua função atual ou em outro ponto antes da virada do loop de execução, você precisa chamar
[view setNeedsLayout]
e[view layoutIfNeeded]
.Você fez uma segunda pergunta: "como posso alterar uma restrição de altura / largura se não tenho uma referência a ela diretamente?".
Se você criar a restrição em IB, a melhor solução é criar um IBOutlet em seu controlador de visão ou em sua visão para que você tenha uma referência direta a ele. Se você criou a restrição no código, deve manter uma referência em uma propriedade interna fraca no momento em que a criou. Se outra pessoa criou a restrição, você precisa encontrá-la examinando o exame da propriedade view.constraints na visão e, possivelmente, toda a hierarquia de visão, e implementando a lógica que encontra o NSLayoutConstraint crucial. Este é provavelmente o caminho errado a seguir, uma vez que também requer efetivamente que você determine qual restrição particular determinou o tamanho dos limites, quando não há garantia de que haja uma resposta simples para essa pergunta. O valor final dos limites pode ser a solução para um sistema muito complicado de múltiplas restrições,
fonte
layoutIfNeeded
é ótimo e tornará o quadro imediatamente disponível. No entanto, também forçará a renderização das restrições em todas as visualizações nas subárvores da visualização na qual é chamada. Se você estiver adicionando visualizações programaticamente, por exemplo, e chamarlayoutIfNeeded
todas elas em sua rotina recursiva, poderá descobrir que sua hierarquia de visualizações renderiza muito lentamente. (Aprendi isso da maneira mais difícil) Como mencionado na excelente resposta, 'setNeedsLayout` é mais eficiente e disponibilizará o quadro na próxima passagem de layout, o que idealmente acontece em cerca de 1/60 de segundo.initWithCoder
?Eu tive um problema semelhante em que precisei adicionar uma borda superior e inferior a um
UITableView
que redimensiona com base em suas configurações de restrições noUIStoryboard
. Consegui acessar as restrições atualizadas com- (void)viewDidLayoutSubviews
. Isso é útil para que você não precise criar uma subclasse de uma visualização e substituir seu método de layout.Sem chamar o método a partir do
viewDidLayoutSubview
método, apenas a borda superior é desenhada corretamente, pois a borda inferior está em algum lugar fora da tela.fonte
[super viewDidLayoutSubviews];
Para aqueles que ainda podem enfrentar esses problemas, especialmente com TableviewCell.
Basta substituir o método:
No caso de UITableViewCell ou UICollectionViewCell, crie uma subclasse da célula e substitua o mesmo método:
fonte
Use
-(void)viewWillAppear:(BOOL)animated
e ligue[self.view layoutIfNeeded];
- Funciona, eu tentei.porque se você usá-
-(void)viewDidLayoutSubviews
lo funcionará definitivamente, mas este método é chamado toda vez que sua IU exige atualizações / mudanças. O que será difícil de gerenciar. A tecla de função é usar uma variável bool para evitar esse loop de chamadas. melhor usoviewWillAppear
. Lembre-viewWillAppear
se também será chamado se a visualização for carregada de volta (sem realocar).fonte
O quadro ainda é válido. No final, a visualização usa sua propriedade frame para se definir. Ele calcula esse quadro com base em todas as restrições. As restrições são usadas apenas para o layout inicial (e sempre que layoutSubviews é chamado em uma vista, como após uma rotação). Depois disso, as informações de posição estão na propriedade do quadro. Ou você está vendo de outra forma?
fonte