Как отменить анимацию на основе блоков UIView?
Я искал множество SO файлов и ссылок Apple, но все же не смог решить свою проблему.
Что у меня:
- с двумя UIImageViews и с ними 2 UIButtons
- 2 вида анимации:
2.1. первый из них масштабируется, затем вниз по каждому изображению, один за другим, только один раз в viewDidLoad
2.2. второй, когда нажата кнопка (которая является настраиваемой кнопкой, скрытой "внутри" каждого UIImageView), она вызывает анимацию соответствующего UIImageView - только один, а не оба (также масштабируется, а затем вниз).
- Как я пишу для iOS4 +, мне говорят использовать анимации на основе блоков!
Что мне нужно:
Как отменить запуск анимации?
Мне удалось отменить все, кроме последнего...:/
Вот мой фрагмент кода:
[UIImageView animateWithDuration:2.0
delay:0.1
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
isAnimating = YES;
self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 2.0, 2.0);
} completion:^(BOOL finished){
if(! finished) return;
[UIImageView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 0.5, 0.5);
} completion:^(BOOL finished){
if(! finished) return;
[UIImageView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 2.0, 2.0);
} completion:^(BOOL finished){
if(! finished) return;
[UIImageView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 0.5, 0.5);
}
completion:^(BOOL finished){
if (!finished) return;
//block letter buttons
[self.bigLetterButton setUserInteractionEnabled:YES];
[self.smallLetterButton setUserInteractionEnabled:YES];
//NSLog(@"vieDidLoad animations finished");
}];
}];
}];
}];
Каким-то образом smallLetter UIImageView работает некорректно, при нажатии (через кнопку) bigLetter отменяет анимацию правильно...
спасибо заранее:)
EDIT:
Я использовал это решение, но все еще имею проблему с уменьшением размера smallLetter UIImageView - не отменяет вообще...
.
EDIT2: Я добавил это в начале следующих/предыдущих методов:
- (void)stopAnimation:(UIImageView*)source {
[UIView animateWithDuration:0.01
delay:0.0
options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction)
animations:^ {
source.transform = CGAffineTransformIdentity;
}
completion:NULL
];
}
проблема остается...:/no idea, как прервать последнюю анимацию для букв в цепочке анимации
Ответы
Ответ 1
Вы можете остановить все анимации на экране, вызвав:
[view.layer removeAllAnimations];
(Вам нужно будет импортировать среду QuartzCore для вызова методов на view.layer).
Если вы хотите остановить определенную анимацию, а не все анимации, лучше всего использовать CAAnimations явно, а не вспомогательные методы анимации UIView, тогда у вас будет более подробный контроль и можно явно остановить анимацию по имени.
Документацию Apple Core Animation можно найти здесь:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html
Ответ 2
Для iOS 10 используйте UIViewPropertyAnimator для анимации.
Он предоставляет методы запуска, остановки и приостановки анимации UIView.
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut){
self.view.alpha = 0.0
}
// Call this to start animation.
animator.startAnimation()
// Call this to stop animation.
animator.stopAnimation(true)
Ответ 3
Я добавлю к Nick ответ, что сделать removeAllAnimations гладкой следующей идеей будет очень удобно.
[view.layer removeAllAnimations];
[UIView transitionWithView:self.redView
duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[view.layer displayIfNeeded];
} completion:nil];
Ответ 4
Когда я работаю с анимацией UIStackView
, кроме removeAllAnimations()
мне нужно установить некоторые значения в начальные значения, потому что removeAllAnimations()
может установить их в непредсказуемое состояние. У меня есть stackView
с view1
и view2
внутри, и один вид должен быть видимым, а другой скрытым:
public func configureStackView(hideView1: Bool, hideView2: Bool) {
let oldHideView1 = view1.isHidden
let oldHideView2 = view2.isHidden
view1.layer.removeAllAnimations()
view2.layer.removeAllAnimations()
view.layer.removeAllAnimations()
stackView.layer.removeAllAnimations()
// after stopping animation the values are unpredictable, so set values to old
view1.isHidden = oldHideView1 // <- Solution is here
view2.isHidden = oldHideView2 // <- Solution is here
UIView.animate(withDuration: 0.3,
delay: 0.0,
usingSpringWithDamping: 0.9,
initialSpringVelocity: 1,
options: [],
animations: {
view1.isHidden = hideView1
view2.isHidden = hideView2
stackView.layoutIfNeeded()
},
completion: nil)
}