Может любой давать категорическое объяснение на отношениях между UIView's
setNeedsLayout
, layoutIfNeeded
и layoutSubviews
методы? И реализация в качестве примера, где все три использовались бы.Спасибо.
То, что получает меня перепутанный, является этим, если я отправляю свое пользовательское представление a setNeedsLayout
передайте очень следующую вещь, которую это вызывает после того, как этот метод layoutSubviews
, пропуск прямо layoutIfNeeded
. Из документов я ожидал бы, что поток будет setNeedsLayout
> причины layoutIfNeeded
быть названным> причины layoutSubviews
быть названным.
Я все еще пытаюсь понять это сам, поэтому отнеситесь к этому с некоторым скептицизмом и простите меня, если он содержит ошибки.
setNeedsLayout
прост: он просто устанавливает флаг где-нибудь в UIView, который отмечает его как требующий макета. Это заставит layoutSubviews
вызываться в представлении до того, как произойдет следующая перерисовка. Обратите внимание, что во многих случаях вам не нужно вызывать это явно из-за свойства autoresizesSubviews
. Если это установлено (что установлено по умолчанию), то любое изменение фрейма представления приведет к тому, что представление будет размещать свои подвиды.
layoutSubviews
- это метод, с помощью которого вы делаете все самое интересное. Если хотите, это эквивалент drawRect
для макета. Тривиальный пример:
-(void)layoutSubviews {
// Child's frame is always equal to our bounds inset by 8px
self.subview1.frame = CGRectInset(self.bounds, 8.0, 8.0);
// It seems likely that this is incorrect:
// [self.subview1 layoutSubviews];
// ... and this is correct:
[self.subview1 setNeedsLayout];
// but I don't claim to know definitively.
}
AFAIK layoutIfNeeded
обычно не предназначен для переопределения в вашем подклассе. Это метод, который вы должны вызывать, когда хотите, чтобы представление было размещено прямо сейчас . Реализация Apple может выглядеть примерно так:
-(void)layoutIfNeeded {
if (self._needsLayout) {
UIView *sv = self.superview;
if (sv._needsLayout) {
[sv layoutIfNeeded];
} else {
[self layoutSubviews];
}
}
}
Вы должны вызвать layoutIfNeeded
в представлении, чтобы заставить его (и, при необходимости, его супервизоры) быть размещенными немедленно.