ios - bottom - swift get safe area top height




Desde o Xcode 8 e iOS10, as visualizações não são dimensionadas corretamente em viewDidLayoutSubviews (8)

Agora, o Interface Builder permite que o usuário altere dinamicamente o tamanho de todos os controladores de visualização no storyboard para simular o tamanho de um determinado dispositivo.

Antes dessa funcionalidade, o usuário deve definir manualmente cada tamanho do controlador de exibição. Assim, o controlador de visualização foi salvo com um determinado tamanho, que foi usado em initWithCoder para definir o quadro inicial.

Agora, parece que o initWithCoder não usa o tamanho definido no storyboard e define um tamanho de 1000x1000 px para a viewcontroller view e todas as suas subvisualizações.

Isso não é um problema, porque as exibições sempre devem usar uma dessas soluções de layout:

  • autolayout, e todas as restrições vão layout corretamente suas opiniões

  • autoresizingMask, que irá traçar cada visualização que não tem nenhuma restrição anexada ( note que autolayout e restrições de margem são agora compatíveis na mesma visão \ o /! )

Mas isso é um problema para todo o material de layout relacionado à camada de visualização, como o cornerRadius , já que nem o autolayout nem a máscara de auto-redimensionamento se aplicam às propriedades da camada.

Para responder a esse problema, a maneira mais comum é usar viewDidLayoutSubviews se você estiver no controlador ou layoutSubview se estiver em uma visualização. Neste ponto (não se esqueça de chamar seus métodos super relativos), você tem certeza de que todo o material de layout foi feito!

Certeza? Hum ... não totalmente, eu comentei, e é por isso que eu fiz esta pergunta, em alguns casos, a visão ainda tem seu tamanho 1000x1000 neste método. Eu acho que não há resposta para minha própria pergunta. Para dar o máximo de informações sobre isso:

1- isso só acontece quando se projetam células! Nas subclasses UITableViewCell e UICollectionViewCell , layoutSubview não será chamado depois que as layoutSubview corretamente organizadas.

2- Como observou o @EugenDimboiu (favoravaliar sua resposta se for útil para você), chamar [myView layoutIfNeeded] na [myView layoutIfNeeded] não-lay out fará o layout corretamente no momento certo.

- (void)layoutSubviews {
    [super layoutSubviews];
    NSLog (self.myLabel); // 1000x1000 size 
    [self.myLabel layoutIfNeeded];
    NSLog (self.myLabel); // normal size
}

3- Na minha opinião, isso é definitivamente um bug. Eu enviei para o radar (id 28562874).

PS: Eu não sou nativo do inglês, então fique à vontade para editar meu post se a minha gramática for corrigida;)

PS2: Se você tiver uma solução melhor, fique à vontade para não escrever outra resposta. Eu moverei a resposta aceita.

Parece que, com o Xcode 8, no viewDidLoad , todas as subvisualizações do viewcontroller têm o mesmo tamanho de 1000x1000. Coisa estranha, mas tudo bem, viewDidLoad nunca foi o melhor lugar para dimensionar corretamente os pontos de vista.

Mas o viewDidLayoutSubviews é!

E no meu projeto atual, tento imprimir o tamanho de um botão:

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    NSLog(@"%@", self.myButton);
}

O log mostra um tamanho de (1000x1000) para myButton! Então, se eu fizer o login em um botão, por exemplo, o log mostra um tamanho normal.

Estou usando o autolayout.

Isso é um bug?


De acordo com nova atualização no ios isso é realmente um bug, mas podemos reduzir isso usando -

Se você estiver usando o xib com autolayout no seu projeto, então você deve apenas atualizar o frame na configuração autolayout, por favor, encontre a imagem para isso.


Eu sei que essa não era a sua pergunta exata, mas eu me deparei com um problema semelhante no qual, como na atualização, algumas das minhas exibições estavam confusas, apesar de ter o tamanho de quadro correto em viewDidLayoutSubviews. De acordo com o iOS 10 Release notes:

"Não é esperado que enviar layoutIfNeeded para uma vista mova a vista, mas em versões anteriores, se a vista tivesse convertidoAutoresizingMaskIntoConstraints definido como NO e se estivesse a ser posicionado por restrições, o layoutIfNeeded moveria a vista para corresponder ao mecanismo de layout antes de enviar o layout para a subárvore.Estas alterações corrigem esse comportamento, e a posição do receptor e normalmente seu tamanho não serão afetadas pelo layoutIfNeeded.

Algum código existente pode estar contando com esse comportamento incorreto que agora é corrigido. Não há mudança de comportamento para binários vinculados antes do iOS 10, mas ao criar no iOS 10 talvez seja necessário corrigir algumas situações enviando -layoutIfNeeded para uma superview da visualização translatesAutoresizingMaskIntoConstraints que era o receptor anterior ou posicionando e dimensionando-o antes ( ou depois, dependendo do seu comportamento desejado) layoutIfNeeded.

Aplicativos de terceiros com subclasses UIView personalizadas usando Auto Layout que substituem layoutSubviews e layout sujo em si antes de chamar super correm o risco de acionar um loop de feedback de layout quando são reconstruídos no iOS 10. Quando são enviadas corretamente as chamadas subseqüentes de layoutSubviews, elas devem pare de sujar o layout em si mesmo em algum momento (note que esta chamada foi ignorada na versão anterior ao iOS 10). "

Essencialmente, você não pode chamar layoutIfNeeded em um objeto filho da View se estiver usando translatesAutoresizingMaskIntoConstraints - agora, chamar layoutIfNeeded deve estar no superView, e você ainda pode chamar isso em viewDidLayoutSubviews.


Isso corrigiu o problema (ridiculamente irritante) para mim:

- (void) viewDidLayoutSubviews {

    [super viewDidLayoutSubviews];

    self.view.frame = CGRectMake(0,0,[[UIScreen mainScreen] bounds].size.width,[[UIScreen mainScreen] bounds].size.height);

}

Editar / Nota: Isto é para um ViewController de tela cheia.


Meu problema foi resolvido alterando o uso de

-(void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    self.viewLoginMailTop.constant = -self.viewLoginMail.bounds.size.height;
}

para

-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];
    self.viewLoginMailTop.constant = -self.viewLoginMail.bounds.size.height;
}

Então, de Did to Will

Super esquisito


Na verdade, viewDidLayoutSubviews também não é o melhor lugar para definir o frame da sua visualização. Tanto quanto eu entendi, a partir de agora o único lugar que deve ser feito é o método layoutSubviews no código da visão atual. Eu gostaria de não estar certo, alguém me corrija, por favor, se não é verdade!


Substituir layoutSublayers (da camada: CALayer) em vez de layoutSubviews na subvisão da célula para ter quadros corretos


Você está usando cantos arredondados para o seu botão? Tente chamar layoutIfNeeded() antes.





xcode8