Ошибка анимации 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
(первый) ошибка исчезла.
4 ответа
У вас есть три анимации:
- Вы оживляете слой
position
- Вы оживляете слой
transform
- Вы оживляете представление
frame
который в свою очередь оживляет слойposition
,
Анимации 1 и 3 сталкиваются.
- На iOS 7 такое поведение, что анимация 3 отменяет анимацию 1.
- На iOS 8 поведение заключается в том, что анимации 1 и 3 запускаются одновременно ("Аддитивные анимации").
Я предлагаю вам просто удалить анимацию 1, а также посмотреть соответствующее видео WWDC 2014 (я думаю, что это было Building Interruptible and Responsive Interactions
).
Для меня работало отключение автолайтов на представлении и ПОДКЛЮЧЕНИЯ к представлению, которое я анимировал в какой-то момент перед анимацией. Отключение автопутешествий из раскадровки было недостаточно в iOS8.
[viewToAnimate removeFromSuperview];
[viewToAnimate setTranslatesAutoresizingMaskIntoConstraints:YES];
//addSubview again at original index
[superView insertSubview:viewToAnimate atIndex:index];
Этот пример может помочь вам, я хотел бы открыть его раньше, чем потратить часы. Вместо того, чтобы оживить 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
в вашем примере.
У меня также возникла небольшая неприятная разница между анимацией iOS7 и iOS8. В большинстве случаев это было сломано, это было либо:
- единственная комбинация Scale, Transform и Rotate CGAffineTransforms - результат зависел от версии iOS
- или сложная последовательность анимаций на разных видах - некоторые виды "сбрасывали" свои позиции перед началом новой части анимации. Около 5% частей анимации были затронуты.
Я почти уверен, что на проблемных видах не было одновременной анимации. Предложения по автоматической разметке и ограничениям не помогли (более того, все анимированные представления были созданы в коде, поскольку автоматическая разметка сильно мешала анимации даже до iOS8).
То, что оказалось универсальным решением для обеих проблем, - это поместить проблемные виды в представление-оболочку и использовать его для разделения анимации вращения или создания анимации, которая вызывает эффект "сброса". Теперь он работает одинаково в 7.1.1 и 8.1.1.