Я хотів би додати у відповідь n8gray, що в деяких випадках вам потрібно буде зателефонувати, setNeedsLayout
після чого layoutIfNeeded
.
Скажімо, для прикладу, що ви написали спеціальний вид, що розширює UIView, в якому позиціонування підвидів є складним і не може бути виконано за допомогою автоматичної розстановки маски або iOS6. Налаштування позиціонування може бути здійснено шляхом переосмислення 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 не встановлений.