UIView анимации с автореверсом - PullRequest
35 голосов
/ 18 февраля 2011

У меня проблема с настройкой 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 ];

Проблема в том, что после переворачивания анимации вид возвращается к кадру, установленному в блоке анимации.Я хочу, чтобы представление росло, «вырастало» и останавливалось в исходном положении.

Есть ли решение без программирования двух последовательных анимаций?

Ответы [ 3 ]

93 голосов
/ 18 февраля 2011

У вас есть три варианта.

Когда вы используете методы -[UIView animateWithDuration:…], изменения, которые вы делаете в блоке animations, применяются немедленно к рассматриваемым представлениям.Однако существует также неявное CAAnimation, примененное к представлению, которое анимирует от старого значения к новому значению.Когда CAAnimation активен в представлении, он изменяет отображаемое представление , но не изменяет фактические свойства представления.

Например, если вы делаете это:

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; }];
   }];

Второй параметр

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

CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
                      delay:0
                    options: UIViewAnimationOptionAutoreverse
                 animations: ^{ someView.center = newPoint; }
                 completion: ^(BOOL finished) { someView.center = oldCenter; }];

Однако, это может вызвать мерцание между временем завершения автореверса анимации и временем выполнения блока завершения.так что, вероятно, это не ваш лучший выбор.

Третий вариант

Последний вариант - просто создать 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. Если это вас пугает, не стесняйтесь использовать вместо него методы -[UIView animateWithDuration:…]. При использовании * 1055 доступны дополнительные функции.*, но если это то, с чем вы не знакомы, цепочка анимаций UIView или сброс ее в блоке завершения вполне приемлемы. Фактически это одна из основных целей блока завершения.

Итак, естьВы идете. Три различных способа перевернуть анимацию и сохранить первоначальное значение. Наслаждайтесь!

14 голосов
/ 26 июля 2012

Вот мое решение. Для повторения 2х анимируйте 1,5х и сделайте последнюю 0,5х часть самостоятельно:

[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 ....

                         }];
                 }];

Нет перепрошивки, хорошо работает.

0 голосов
/ 18 февраля 2011

На CAMediaTiming имеется свойство repeatCount. Я думаю, что вы должны создать явный объект 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 Нет способа избежать программирования двух анимационных объектов.

...