Анимация UIView с помощью autoreverse
у меня проблема с настройкой UIViewAnimationOptionAutoReverse
.
Вот мой код.
CALayer *aniLayer = act.viewToChange.layer;
[UIView animateWithDuration:2.0 delay:1.0 options:(UIViewAnimationCurveLinear | UIViewAnimationOptionAutoreverse) animations:^{
viewToAnimate.frame = GCRectMake(1,1,100,100);
[aniLayer setValue:[NSNumber numberWithFloat:degreesToRadians(34)] forKeyPath:@"transform.rotation"];
} completion:nil ];
проблема в том, что после того, как анимация была отменена, представление возвращается к кадру, установленному в блоке анимации. Я не хочу, чтобы расти и "ungrow" и остановится в исходном положении.
есть ли решение без программирования двух последовательных анимаций?
3 ответов
у вас есть три варианта.
при использовании -[UIView animateWithDuration:…]
методы, изменения, которые вы делаете в animations
блок применяются немедленно к рассматриваемым представлениям. Однако существует также неявное CAAnimation
применяется к представлению, которое анимирует от старого значения к новому значению. Когда CAAnimation
активен в представлении, он изменяет отображается view, но не изменяет фактические свойства представления.
например, если вы делаете это:
NSLog(@"old center: %@", NSStringFromCGPoint(someView.center));
[UIView animateWithDuration:2.0 animations: ^{ someView.center = newPoint; }];
NSLog(@"new center: %@", NSStringFromCGPoint(someView.center));
вы увидите, что "старый центр" и "новый центр" разные; новый центр будет тут отражают значения newPoint. Однако CAAnimation
, что косвенно приводит мнение еще отображается в старом центре и плавно двигаться свой путь в новый центр. Когда анимация завершается, она удаляется из представления, и вы переключаетесь на просмотр фактических значений модели.
когда вы проходите UIViewAnimationOptionAutoreverse
, это влияет на неявно создан CAAnimation
, но не влияет на фактическое изменение, которое вы делаете для значений. То есть, если бы наш пример выше имел UIViewAnimationOptionAutoreverse
определено, затем неявно создано CAAnimation
будет анимироваться из oldCenter в newCenter и обратно. Затем анимация будет удалена, и мы вернемся к просмотру значений, которые мы установили... что еще за новая позиция.
Первый Вариант
CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
animations: ^{ someView.center = newPoint; }
completion:
^(BOOL finished) {
[UIView animateWithDuration:2.0
animations:^{ someView.center = oldCenter; }];
}];
Второй Вариант
второй вариант состоит в том, чтобы autoreverse анимации, как вы делаете, и установить вид обратно в исходное положение в блоке завершения:
CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
delay:0
options: UIViewAnimationOptionAutoreverse
animations: ^{ someView.center = newPoint; }
completion: ^(BOOL finished) { someView.center = oldCenter; }];
тем не менее, это может вызвать мерцание между временем завершения анимации autoreverse и когда блок завершения выполняется, так что это, вероятно, не ваш лучший выбор.
Третий Вариант
последний вариант-просто создать CAAnimation
напрямую. Когда вы на самом деле не хотите изменять конечное значение изменяемого свойства, это часто проще.
#import <QuartzCore/QuartzCore.h>
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.autoreverses = YES;
animation.repeatCount = 1; // Play it just once, and then reverse it
animation.toValue = [NSValue valueWithCGPoint:newPoint];
[someView.layer addAnimation:animation forKey:nil];
отметим, что CAAnimation
способ делать вещи никогда не изменяет фактические значения вид; оно просто маскирует фактические значения с анимацией. Вид все еще думает, что он в исходном месте. (Это означает, например, что если ваш взгляд реагирует на сенсорные события, он по-прежнему будет наблюдать за этими сенсорными событиями в исходном месте. Анимация только изменяет способ рисования вида; ничего больше.
на CAAnimation
путь также требует, чтобы вы добавили его в базовое представление CALayer
. Если это пугает вас, не стесняйтесь использовать методы. Существует дополнительная функциональность, доступная с помощью CAAnimation
, но если это что-то, с чем вы не знакомы, цепочка UIView анимация или сброс его в блоке завершения вполне приемлемы. На самом деле, это одна из основных целей блока завершения.
Итак, вот ты где. Три разных способа отменить анимацию и сохранить исходное значение. Наслаждайтесь!
вот мое решение. Для 2x повторите, анимируйте 1.5 x и сделайте последнюю часть 0.5 x самостоятельно:
[UIView animateWithDuration:.3
delay:.0f
options:(UIViewAnimationOptionRepeat|
UIViewAnimationOptionAutoreverse)
animations:^{
[UIView setAnimationRepeatCount:1.5f];
... animate here ...
} completion:^(BOOL finished) {
[UIView animateWithDuration:.3 animations:^{
... finish the animation here ....
}];
}];
нет мигания, работает хорошо.
есть repeatCount
свойство on CAMediaTiming
. Я думаю, вы должны создать явный CAAnimation
объект и настройте его правильно. RepeatCount для grow и ungrow будет 2, но вы можете проверить это.
что-то долго ждать этого. Вы бы хоть нужны два объекта CAAnimation, одна для каркаса и для ротации.
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation"];
theAnimation.duration=3.0;
theAnimation.repeatCount=1;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSNumber numberWithFloat:0.0];
theAnimation.toValue=[NSNumber numberWithFloat:degreesToRadians(34)];
[theLayer addAnimation:theAnimation forKey:@"animateRotation"];
AFAIK нет способа избежать программирования двух объектов анимации.