CATransition推送过渡早期替换内容

时间:2012-11-09 04:21:07

标签: ios macos cocoa core-animation caanimation

我在Mac App中进行了简单的动画设置,其中页面控件交换了一些视图。我非常接近获得我想要的分页式动画,但是有一个小问题。分页工作正常,新页面正确设置到位,但新页面也会在动画之前替换初始页面。我希望最终将推出的视图保持不变,而不是尽早更改为新页面。 Here is a video showing the problem,减慢到3秒的动画持续时间。这是代码:

UASourceView *previousSourceView = [self.sourceViewContainer.subviews objectAtIndex:0];
NSInteger previousIndex = [self.sourceViews indexOfObjectIdenticalTo:previousSourceView];

CATransition *pushTransition = [CATransition animation];
[pushTransition setType:kCATransitionPush];
[pushTransition setSubtype:(previousIndex < index) ? kCATransitionFromRight : kCATransitionFromLeft];
[pushTransition setDuration:PANEL_PAGE_SWIPE_ANIMATION_DURATION];
[pushTransition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[pushTransition setRemovedOnCompletion:YES];

[CATransaction begin];
[self.sourceViewContainer replaceSubview:previousSourceView with:sourceView];
[CATransaction commit];

[sourceView.layer addAnimation:pushTransition forKey:@"push"];

有一个固定的容器视图self.sourceViewContainer,可以在每个动画中替换一个新的子视图。如上所示,问题在于previousSourceView 会立即替换sourceView,并且也会被推入。请帮我停止立即更换。我哪里错了?

*注意,添加了iOS标记,因为此代码与平台无关。

1 个答案:

答案 0 :(得分:1)

我使用CAAnimationBlocks解决了类似的问题(这是我original的分支,作者已朝我不太关心的方向移动了。)

我们的想法是将removedOnCompletion设置为NO,将fillMode设置为kCAFillModeForwards,并在完成块中执行实际切换(不带动画)。这已在OSX下测试过(您可能需要一个不同的iOS解决方案,它已经支持完成块)。

以下是我的代码中的一个示例用法,它在棋盘上移动一块,然后再移回:

CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
moveAnimation.fromValue = [NSValue valueWithPoint:[self _pointForSquare:move.from()]];
moveAnimation.toValue = [NSValue valueWithPoint:[self _pointForSquare:move.to()]];
moveAnimation.duration = _animateSpeed / 1000.0;
moveAnimation.autoreverses = YES;
moveAnimation.removedOnCompletion = NO;
moveAnimation.fillMode = kCAFillModeForwards;
moveAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
moveAnimation.completion = ^(BOOL finished)
{
    [pieceLayer removeAnimationForKey:@"movePiece"];
    [self _setPieceLayer:pieceLayer toPiece:piece];
    [pieceLayer setNeedsDisplay];
};

[pieceLayer addAnimation:moveAnimation forKey:@"movePiece"];