MayoutoutSubviews во время анимации?
-
02-10-2019 - |
Вопрос
у меня есть UIView
с кучей подписаний, все расположены с использованием layoutSubviews
. Анкет Когда view
Изменен, относительные позиции все изменяются. Я бы хотел, чтобы эти повторные рассчинения произошли во время анимированного изменения размера (используя +[UIView beginAnimations:]
вызовы). Это, похоже, не происходит. Любые идеи?
Решение
Предположение: вы хотите иметь несколько шагов анимации (т.е. позиция не меняется линейно с размером кадра).
Это невозможно при единой «стандартной» анимации Uiview. Почему? Кадр/границы устанавливаются только один раз.
Основная анимация Имеет три «слои -деревья»:
- А Модельное дерево Это где ваше приложение думает, что все есть.
- А Дерево презентации Примерно то, что отображается на экране.
- А рендеринг дерево Примерно то, какая основная анимация является композицией.
Uiview - это (несколько тонкая) обертка вокруг слоя модели. Во время анимации Uiview основная анимация обновляет дерево презентации/рендеринга - дерево модели представляет конечную точку анимации. В результате ваш код может (по большей части) рассматривать анимации как мгновенное, перемещая вид от A к B мгновенно перемещает его в B; Изменение просто анимировано с пользователем.
Есть более сложные вещи, которые вы можете сделать с Calayer/Caanimation напрямую, но я не исследовал так много.
Вы можете объединить несколько анимаций вместе, используя -[uiview setanimationdidstopselector:]. (Вы также можете попробовать использовать несколько анимаций вместе с SetanimationDelay:, но я не уверен, что происходит с несколькими анимациями на одном и том же свойстве; вам может повезло с SetanimationBeginsfromCurrentState :.)
Если вам нужен действительно мелкозернистый контроль, CadisPlayLink (OS 3.1+)-это таймер, который стреляет после каждого экрана обновления. Опция завышенного (для поддержки 3.0) - использовать NSTIMER при 30/60 Гц или около того.
Другие советы
Завершив @Gizzlynetch's Anwer, вы можете установить UIViewAnimationOptionLayoutSubviews
опция анимации, поэтому вам не нужно звонить layoutIfNeeded
:
-(void)someMethod{
double duration = ...;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
self.frame = ...;
} completion:nil];
}
Я знаю, что это старый вопрос, но этот код работает для меня очень хорошо (подходит для вашего примера изменения кадра).
-(void)layoutSubviews{
[super layoutSubviews];
// layout your subviews here, or whatever
}
-(void)someMethod{
double duration=...;
[UIView animateWithDuration:duration animations:^{
self.frame = ...;
[self layoutIfNeeded];
}];
}
Конечно, вы можете назвать этот метод из другого объекта. «Трюк» состоит в том, чтобы вызовать Layoutifneeded (или LayoutoutSupwies напрямую - то же самое, если вы измените кадр, называется SetNeedSlayout).
Как TC. Хорошо объяснил «слойные деревья», вы просто заставляете слой презентации отобразить последний этап уровня модели с анимацией.
Преимущество этого метода заключается в возможности управления, когда изменение кадра/границы анимировано и когда оно мгновенно.
Надеюсь, это кому -то поможет :).
Публикация для полноты. Спасибо TC. Для объяснения того, что я хочу сделать, точно не поддерживается основной анимацией.
В конце концов я придумал разумное решение. Вместо того, потом макет мои подвесития в -layoutsubviews, я делаю это в -седбендс:. Затем, когда я обертываю hetbounds: звоните в Uiview +BeginAnimations: Block, эти вызовы позиционирования также анимированы, и конечный результат -все, что правильно оживляет, где он должен Бог.