Отменить анимацию UIView?
можно ли отменить a UIView анимация во время ее выполнения? Или мне придется опуститься до уровня CA?
т. е. я сделал что-то вроде этого (возможно, установив действие анимации конца тоже):
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// other animation properties
// set view properties
[UIView commitAnimations];
но до того, как анимация завершится, и я получу событие animation ended, я хочу отменить его (сократить его). Это возможно? Поиск в интернете обнаруживает, что несколько человек задают один и тот же вопрос без ответов - и один или два человека предполагают, что это это невозможно сделать.
15 ответов:
Как я это делаю, чтобы создать новую анимацию для вашей конечной точки. Установите очень короткую продолжительность и убедитесь, что вы используете
+setAnimationBeginsFromCurrentState:способ начать с текущего состояния. Когда вы устанавливаете его в да, текущая анимация прерывается. Выглядит примерно так:[UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:0.1]; [UIView setAnimationCurve: UIViewAnimationCurveLinear]; // other animation properties // set view properties [UIView commitAnimations];
самый простой способ остановить все анимация на определенном виде,тут это:
свяжите проект с QuartzCore.рамки. В начале кода:
#import <QuartzCore/QuartzCore.h>теперь, когда вы хотите, чтобы остановить все анимации на вид мертвых в своих треках, скажите это:
[CATransaction begin]; [theView.layer removeAllAnimations]; [CATransaction commit];средняя линия будет работать сама по себе, но есть задержка до завершения runloop ("перерисовка момент"). Чтобы предотвратить эту задержку, оберните команду в явном блоке транзакций, как показано на рисунке. Это работает при условии, что никакие другие изменения не были выполнены на этом уровне в текущем runloop.
на 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; } }]; }
чтобы отменить анимацию, вам просто нужно установить свойство, которое в настоящее время анимируется, вне анимации UIView. Это остановит анимацию, где бы она ни была, и UIView перейдет к настройке, которую вы только что определили.
Извините, что воскрешаю этот ответ, но в iOS 10 все изменилось, и теперь отмена возможна, и вы даже можете отменить изящно!
после iOS 10 вы можете отменить анимацию с помощью UIViewPropertyAnimator!
UIViewPropertyAnimator(duration: 2, dampingRatio: 0.4, animations: { view.backgroundColor = .blue }) animator.stopAnimation(true)Если вы передаете true, он отменяет анимацию и останавливается прямо там, где вы ее отменили. Метод завершения не будет вызван. Однако, если вы передаете false, вы несете ответственность за завершение анимация:
animator.finishAnimation(.start)вы можете закончить анимацию и остаться в текущем состоянии (.текущий) или перейти в исходное состояние (.начало) или до конечного состояния (.конец)
кстати, вы даже можете приостановить и перезапустить позже...
animator.pauseAnimation() animator.startAnimation()Примечание: Если вы не хотите резкого отмены вы можете изменить свою анимацию или даже изменить анимацию после того, как вы приостановите его!
Если вы анимируете ограничение, изменяя константу вместо свойства view, ни один из других методов не работает на 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]; }
Если вы просто хотите, чтобы приостановить/остановить анимацию плавно
self.yourView.layer.speed = 0;источник: как приостановить анимацию дерева слой
ни один из вышеперечисленных не решил его для меня, но это помогло:
UIViewанимация устанавливает свойство немедленно, а затем анимирует его. Он останавливает анимацию, когда слой представления соответствует модели (свойство set).Я решил свою проблему, которая заключалась в том, что "я хочу анимировать, откуда вы выглядите так, как вы выглядите" ("вы" означает вид). Если вы этого хотите, то:
- Добавить QuartzCore.
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) {}];и это должно быть достойным решением на данный момент.
у меня та же проблема; API не имеют ничего, чтобы отменить некоторые конкретные анимации. Элемент
+ (void)setAnimationsEnabled:(BOOL)enabledотключает все анимации, и, таким образом, не работает для меня. Есть два решения:
1) Сделайте свой анимированный объект подвидом. Затем, когда вы хотите отменить анимацию для этого представления, удалите представление или скройте его. Очень просто, но вам нужно воссоздать подвид без анимации, если вам нужно держать его в поле зрения.
2) повторить аним только один, и сделать селектор делегата, чтобы перезапустить аним, если это необходимо, например:
-(void) startAnimation { NSLog(@"startAnim alpha:%f", self.alpha); [self setAlpha:1.0]; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:1.0]; [UIView setAnimationRepeatCount:1]; [UIView setAnimationRepeatAutoreverses:YES]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(pulseAnimationDidStop:finished:context:)]; [self setAlpha:0.1]; [UIView commitAnimations]; } - (void)pulseAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { if(hasFocus) { [self startAnimation]; } else { self.alpha = 1.0; } } -(void) setHasFocus:(BOOL)_hasFocus { hasFocus = _hasFocus; if(hasFocus) { [self startAnimation]; } }проблема с 2) заключается в том, что всегда есть задержка остановки Анима, когда он заканчивает текущий цикл анимации.
надеюсь, что это помогает.
даже если вы отмените анимацию в пути анимации выше
didStopSelectorпо-прежнему работает. Поэтому, если у вас есть логические состояния в вашем приложении, управляемые анимацией, у вас будут проблемы. По этой причине с описанными выше способами я использую контекстную переменнуюUIViewанимация. Если вы передаете текущее состояние своей программы по контекстному параметру в анимацию, когда анимация останавливает вашdidStopSelectorфункция может решить, следует ли ей что-то делать или просто вернуться на основе текущего состояния и государственное значение, переданное в качестве контекста.
CALayer * pLayer = self.layer.presentationLayer; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView animateWithDuration:0.001 animations:^{ self.frame = pLayer.frame; }];
чтобы приостановить анимацию без возврата в исходное или конечное состояние:
CFTimeInterval paused_time = [myView.layer convertTime:CACurrentMediaTime() fromLayer:nil]; myView.layer.speed = 0.0; myView.layer.timeOffset = paused_time;
Swift версия решения Стивена Дарлингтона
UIView.beginAnimations(nil, context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(0.1) // other animation properties // set view properties UIView.commitAnimations()
Comments