Отменить анимацию UIView? - PullRequest
       25

Отменить анимацию UIView?

238 голосов
/ 17 февраля 2009

Можно ли отменить анимацию UIView во время ее выполнения? Или мне придется опуститься до уровня CA?

т.е. Я сделал что-то вроде этого (возможно, установил действие окончания анимации тоже):

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];

Но прежде чем анимация завершится и я получу событие завершения анимации, я хочу отменить его (сократить его). Это возможно? В поисках гугла находят несколько человек, которые задают один и тот же вопрос без ответов - и один или два человека гадают, что это невозможно сделать.

Ответы [ 16 ]

357 голосов
/ 19 марта 2010

Использование:

#import <QuartzCore/QuartzCore.h>

.......

[myView.layer removeAllAnimations];
113 голосов
/ 09 мая 2009

То, как я это делаю, - это создание новой анимации для вашей конечной точки. Установите очень короткую продолжительность и убедитесь, что вы используете метод +setAnimationBeginsFromCurrentState: для запуска из текущего состояния. Когда вы устанавливаете его в YES, текущая анимация обрывается. Выглядит примерно так:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.1];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties

// set view properties

[UIView commitAnimations];
62 голосов
/ 04 января 2012

Самый простой способ остановить все анимации в определенном представлении, немедленно , это:

Свяжите проект с QuartzCore.framework. В начале вашего кода:

#import <QuartzCore/QuartzCore.h>

Теперь, когда вы хотите остановить все анимации на представлении, мертвом в своих треках, скажите это:

[CATransaction begin];
[theView.layer removeAllAnimations];
[CATransaction commit];

Средняя линия будет работать сама по себе, но есть задержка, пока не завершится цикл запуска («момент перерисовки»). Чтобы предотвратить эту задержку, оберните команду в явный блок транзакции, как показано. Это работает, если в текущем цикле выполнения не было выполнено никаких других изменений в этом слое.

47 голосов
/ 11 августа 2011

В iOS 4 и выше, используйте параметр UIViewAnimationOptionBeginFromCurrentState для второй анимации, чтобы сократить первую анимацию.

В качестве примера предположим, что у вас есть представление с индикатором активности. Вы хотите добавить индикатор активности в то время, когда начинается какое-то потенциально трудоемкое действие, и затемнить его, когда действие закончится. В приведенном ниже коде представление с индикатором активности называется activityView.

- (void)showActivityIndicator {
    activityView.alpha = 0.0;
    activityView.hidden = NO;
    [UIView animateWithDuration:0.5
                 animations:^(void) {
                     activityView.alpha = 1.0;
                 }];

- (void)hideActivityIndicator {
    [UIView animateWithDuration:0.5
                 delay:0 options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^(void) {
                     activityView.alpha = 0.0;
                 }
                 completion:^(BOOL completed) {
                     if (completed) {
                         activityView.hidden = YES;
                     }
                 }];
}
40 голосов
/ 19 июня 2010

Чтобы отменить анимацию, вам просто нужно установить свойство, которое в данный момент анимируется, вне анимации UIView. Это остановит анимацию, где бы она ни находилась, и UIView перейдет к настройке, которую вы только что определили.

20 голосов
/ 09 ноября 2017

Извините, что воскресил этот ответ, но в iOS 10 все изменилось, и теперь отмена возможна, и вы даже можете отменить изящно!

После iOS 10 вы можете отменить анимацию с помощью UIViewPropertyAnimator !

UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: {
    view.backgroundColor = .blue
})
animator.stopAnimation(true)

Если вы передадите true, анимация будет отменена и остановится там, где вы ее отменили. Метод завершения не будет вызван. Однако, если вы передадите false, вы несете ответственность за завершение анимации:

animator.finishAnimation(.start)

Вы можете закончить анимацию и оставаться в текущем состоянии (.current) или перейти в исходное состояние (.start) или в конечное состояние (.end)

Кстати, вы можете даже приостановить и перезапустить позже ...

animator.pauseAnimation()
animator.startAnimation()

Примечание. Если вы не хотите резкой отмены, вы можете отменить анимацию или даже изменить анимацию после ее приостановки!

9 голосов
/ 07 ноября 2014

Если вы анимируете ограничение, изменяя константу вместо свойства представления, ни один из других методов не работает в iOS 8.

Пример анимации:

self.constraint.constant = 0;
[self.view updateConstraintsIfNeeded];
[self.view layoutIfNeeded];
[UIView animateWithDuration:1.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveLinear
                 animations:^{
                     self.constraint.constant = 1.0f;
                     [self.view layoutIfNeeded];
                 } completion:^(BOOL finished) {

                 }];

Решение:

Вам необходимо удалить анимацию из слоев любых видов, на которые влияет изменение ограничения, и их подслоев.

[self.constraintView.layer removeAllAnimations];
for (CALayer *l in self.constraintView.layer.sublayers)
{
    [l removeAllAnimations];
}
8 голосов
/ 29 июня 2015

Если вы просто хотите плавно приостановить / остановить анимацию

self.yourView.layer.speed = 0;

Источник: Как приостановить анимацию дерева слоев

5 голосов
/ 06 февраля 2015
[UIView setAnimationsEnabled:NO];
// your code here
[UIView setAnimationsEnabled:YES];
5 голосов
/ 16 августа 2011

Ничто из вышеперечисленного не решило это для меня, но это помогло: анимация UIView сразу устанавливает свойство, а затем анимирует его. Останавливает анимацию, когда уровень представления соответствует модели (свойство set).

Я решил свою проблему, которая была «Я хочу анимировать, откуда вы выглядите, как вы выглядите» («вы» означает представление). Если вы хотите ЭТО, то:

  1. Добавить QuartzCore.
  2. CALayer * pLayer = theView.layer.presentationLayer;

установить положение на уровне представления

Я использую несколько опций, включая UIViewAnimationOptionOverrideInheritedDuration

Но поскольку документация Apple является расплывчатой, я не знаю, действительно ли она перекрывает другие анимации при использовании или просто сбрасывает таймеры.

[UIView animateWithDuration:blah... 
                    options: UIViewAnimationOptionBeginFromCurrentState ... 
                    animations: ^ {
                                   theView.center = CGPointMake( pLayer.position.x + YOUR_ANIMATION_OFFSET, pLayer.position.y + ANOTHER_ANIMATION_OFFSET);
                   //this only works for translating, but you get the idea if you wanna flip and scale it. 
                   } completion: ^(BOOL complete) {}];

И сейчас это должно быть достойным решением.

...