Gostaria de acrescentar a resposta do n8gray que, em alguns casos, você precisará ligar setNeedsLayout
seguido por layoutIfNeeded
.
Digamos, por exemplo, que você escreveu uma visualização customizada estendendo UIView, na qual o posicionamento de subvisualizações é complexo e não pode ser feito com autoresizingMask ou iOS6 AutoLayout. O posicionamento personalizado pode ser feito substituindo layoutSubviews
.
Como exemplo, digamos que você tenha uma visualização personalizada que possui uma contentView
propriedade e uma edgeInsets
propriedade que permite definir as margens ao redor de contentView. layoutSubviews
ficaria assim:
- (void) layoutSubviews {
self.contentView.frame = CGRectMake(
self.bounds.origin.x + self.edgeInsets.left,
self.bounds.origin.y + self.edgeInsets.top,
self.bounds.size.width - self.edgeInsets.left - self.edgeInsets.right,
self.bounds.size.height - self.edgeInsets.top - self.edgeInsets.bottom);
}
Se você deseja poder animar a mudança de quadro sempre que alterar a edgeInsets
propriedade, você precisa substituir o configurador da edgeInsets
seguinte maneira e chamar setNeedsLayout
seguido por layoutIfNeeded
:
- (void) setEdgeInsets:(UIEdgeInsets)edgeInsets {
_edgeInsets = edgeInsets;
[self setNeedsLayout]; //Indicates that the view needs to be laid out
//at next update or at next call of layoutIfNeeded,
//whichever comes first
[self layoutIfNeeded]; //Calls layoutSubviews if flag is set
}
Dessa forma, se você fizer o seguinte, se alterar a propriedade edgeInsets dentro de um bloco de animação, a mudança de quadro de contentView será animada.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Se você não adicionar a chamada para layoutIfNeeded no método setEdgeInsets, a animação não funcionará porque o layoutSubviews será chamado no próximo ciclo de atualização, o que equivale a chamá-lo fora do bloco de animação.
Se você chamar layoutIfNeeded no método setEdgeInsets, nada acontecerá, pois o sinalizador setNeedsLayout não está definido.