Я хотел бы добавить к ответу n8gray, что в некоторых случаях вам нужно будет позвонить, setNeedsLayout
а затем layoutIfNeeded
.
Предположим, например, что вы написали настраиваемое представление, расширяющее UIView, в котором размещение вложенных представлений является сложным и не может быть выполнено с помощью autoresizingMask или iOS6 AutoLayout. Пользовательское позиционирование может быть выполнено путем переопределения layoutSubviews
.
В качестве примера предположим, что у вас есть настраиваемое представление, у которого есть contentView
свойство и edgeInsets
свойство, которое позволяет устанавливать поля вокруг contentView. layoutSubviews
будет выглядеть так:
- (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);
}
Если вы хотите иметь возможность анимировать смену кадра всякий раз, когда вы меняете edgeInsets
свойство, вам нужно переопределить edgeInsets
установщик следующим образом и вызвать, setNeedsLayout
за которым следует 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
}
Таким образом, если вы сделаете следующее, если вы измените свойство edgeInsets внутри блока анимации, изменение кадра contentView будет анимировано.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Если вы не добавите вызов layoutIfNeeded в методе setEdgeInsets, анимация не будет работать, потому что layoutSubviews будет вызываться в следующем цикле обновления, что равносильно его вызову вне блока анимации.
Если вы вызываете только layoutIfNeeded в методе setEdgeInsets, ничего не произойдет, поскольку флаг setNeedsLayout не установлен.