Реализация CATransition push с помощью CAAnimation

Как вы реализуете kCATransitionPush с помощью CAAnimation подклассов в iOS?

CAAnimation *animation;
// How do you create an animation that does the same than:
// CATransition *animation = [CATransition animation];
// [animation setType:kCATransitionPush];        
[self.view.layer addAnimation:animation forKey:nil];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];        
[self.view addSubview:change];
[UIView commitAnimations];

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


person hpique    schedule 09.04.2011    source источник


Ответы (2)


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

[nextView.layer addAnimation:nextViewAnimation forKey:nil];
[currentView.layer addAnimation:currentViewAnimation forKey:nil];

nextViewAnimation будет:

CAAnimationGroup *nextViewAnimation = [CAAnimationGroup animation];
NSMutableArray *nextAnimations = [NSMutableArray array];

[nextAnimations addObject:[self opacityAnimation:YES]];  // fade in

CGPoint fromPoint = CGPointMake(forward ? nextView.center.x + nextView.frame.size.width : nextView.center.x - nextView.frame.size.width, nextView.center.y);
[nextAnimations addObject:[self positionAnimationFromPoint:fromPoint toPoint:nextView.center]];  // traslation in

nextViewAnimation.animations = nextAnimations;

и текущийViewAnimation:

CAAnimationGroup *currentViewAnimation = [CAAnimationGroup animation];
NSMutableArray *currentAnimations = [NSMutableArray array];
[currentSceneAnimations addObject:[self opacityAnimation:NO]]; // fade out

CGPoint toPoint = CGPointMake(forward ? currentView.center.x - currentView.frame.size.width : currentView.center.x + currentView.frame.size.width, currentView.center.y);
    [currentAnimations addObject:[self positionAnimationFromPoint:currentView.center toPoint:toPoint]];  // traslation out

currentViewAnimation.animations = currentAnimations;

Эти методы создают основные анимации:

- (CABasicAnimation *)opacityAnimation:(BOOL)fadeIn {
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"];
a.fromValue = [NSNumber numberWithFloat:fadeIn ? 0.0 : 1.0];
a.toValue = [NSNumber numberWithFloat:fadeIn ? 1.0 : 0.0];
return a;
}

- (CABasicAnimation *)positionAnimationFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"position"];
a.fromValue = [NSValue valueWithCGPoint:fromPoint];
a.toValue = [NSValue valueWithCGPoint:toPoint];
return a;
}

С помощью логического значения forward вы можете имитировать переход "слева" или "справа".

person LoDani    schedule 24.10.2011

Значение по умолчанию kCATransitionPush действительно включает затухание. Чтобы воспроизвести переход с помощью собственного CABasicAnimation, вам сначала нужно понять, как работает анимация толчка. Я делаю это без тестирования, так что это может быть отключено, но, если я правильно помню, анимация, в которой подслой B заменяет подслой A, работает следующим образом:

  • Слой A перемещается из исходного положения вправо
  • Слой B перемещается справа на исходное положение A
  • Первая половина анимационного слоя B анимирует свою непрозрачность от 0 до 1.
  • Вторая половина анимационного слоя A изменяет свою непрозрачность от 1 до 0 (конечно, здесь вы можете заменить right на любое направление).

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

Создайте анимацию для положения и непрозрачности следующим образом:

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
anim.fromValue = [NSValue valueWithCGPoint:startPoint];
anim.toValue = [NSValue valueWithCGPoint:endPoint];

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
anim.fromValue = [NSNumber numberWithFloat:0.0];
anim.toValue = [NSNumber numberWithFloat:1.0];
person Joris Kluivers    schedule 12.04.2011
comment
Спасибо Йорис. Это не вид A, который заменяет вид B. Это исходное состояние представления, которое заменяется новым состоянием. - person hpique; 13.04.2011
comment
Извините, я каким-то образом использую слово view вместо CALayer. Переход действительно работает с содержимым View: я не знаю реализации Apple, возможно, это OpenGL, поддерживающий анимацию содержимого CALayer. Лучший способ сделать это самостоятельно - это применить описанный выше способ к подслоям. - person Joris Kluivers; 13.04.2011
comment
Как вы различаете подуровень A и подуровень B? CATransition делает это автоматически. - person hpique; 17.10.2011