Ошибка анимации iOS 8
У меня есть простой способ просмотра анимации.
-(void)animateSelf
{
CABasicAnimation * animation;
animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
// settings ...
[self.view.layer addAnimation:animation forKey:@"position.y"];
animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
// settings ...
[self.view.layer addAnimation:animation forKey:@"transform.rotation.z"];
[UIView animateWithDuration: 1.0 animations:^{
CGRect rect = self.view.frame;
rect.origin.y += 800;
self.view.frame = rect;
} completion:nil];
}
Для iOS 7 он работал хорошо. Но для iOS 8 анимация ведет себя непредсказуемо. Есть ли способ объединить эти анимации для iOS 8?
Я попытался заменить animateWithDuration: другим CABasicAnimation, но это не помогло.
Журналы view.frame верны, но анимация view.frame выпрыгивает из неясного происхождения.
После удаления CABasicAnimation для position.y
(первого) ошибка исчезла.
Ответы
Ответ 1
У вас есть три анимации:
- Вы анималируете слой
position
- Вы анималируете слой
transform
- Вы анимируете представление
frame
, которое, в свою очередь, анимирует слой position
.
Анимации 1 и 3 сталкиваются.
- В iOS 7 поведение заключается в том, что анимация 3 отменяет анимацию 1.
- В iOS 8 поведение заключается в том, что анимации 1 и 3 выполняются одновременно ( "Additive Animations" ).
Я предлагаю вам просто удалить анимацию 1, а также проверить связанный видеоролик WWDC 2014 (я думаю, что это было Building Interruptible and Responsive Interactions
).
Ответ 2
Что сработало для меня, так это отключить автозапуск в представлении и SUBVIEWS представления, которое я анимационировал в какой-то момент перед анимацией. Отключение автоспуска из раскадровки было недостаточно в iOS8.
[viewToAnimate removeFromSuperview];
[viewToAnimate setTranslatesAutoresizingMaskIntoConstraints:YES];
//addSubview again at original index
[superView insertSubview:viewToAnimate atIndex:index];
Ответ 3
Этот пример может помочь вам, мне жаль, что я не обнаружил его, прежде чем тратить часы. Вместо анимации frame
анимируется его contraints
. Нажмите на ограничение автоматического макета, которое вы хотите настроить (в построителе интерфейса, например, в верхнем ограничении). Затем сделайте это IBOutlet;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;
Анимация вверх;
self.topConstraint.constant = -100;
[self.viewToAnimate setNeedsUpdateConstraints];
[UIView animateWithDuration:1.5 animations:^{
[self.viewToAnimate layoutIfNeeded];
}];
Анимация назад в исходное место
self.topConstraint.constant = 0;
[self.viewToAnimate setNeedsUpdateConstraints];
[UIView animateWithDuration:1.5 animations:^{
[self.viewToAnimate layoutIfNeeded];
}];
Первоначально отправленный мной здесь
Итак, вы бы скорректировали ограничение для self.view.frame
в вашем примере.
Ответ 4
У меня также возникла проблема с небольшими неприятными различиями между анимацией iOS7 и iOS8.
В большинстве случаев это было сломано:
- единственная комбинация масштабирования, преобразования и поворота CGAffineTransforms - результат зависел от версии iOS
- или сложная последовательность анимаций на разных представлениях - некоторые представления "переписывали" свои позиции перед началом нового фрагмента анимации. Было затронуто около 5% фрагментов анимации.
Я уверен, что одновременных анимаций в проблемных представлениях не было.
Предложения Autolayout и ограничений не помогли (более того, все анимированные представления были созданы в коде, поскольку автоматическое отключение сильно искажало анимацию даже до iOS8).
То, что оказалось универсальным решением для обеих задач, состоит в том, чтобы помещать проблематичные представления в представление оболочки и использовать его для разделения анимации вращения или сделать анимацию, которая вызывает эффект "reset". Теперь он функционирует одинаково в 7.1.1 и 8.1.1.