使用CAKeyframeAnimation为图层位置设置动画

时间:2015-02-22 17:20:17

标签: ios objective-c core-animation cabasicanimation cakeyframeanimation

我在所有互联网网站上挖掘并找不到解决方案。我的问题是用CAKeyframeAnimation改变CALayer的位置。动画结束后,我无法设置图层位置的最终值(位置重置为最终值)。所有教程,示例和答案都包含两个信息:在向图层添加动画之前或之后将最终值设置为模型图层(换句话说,立即),但这不能按预期工作。取而代之的是我必须在CATransaction的完成块中设置最终值,但这会导致闪烁(图层的位置重置为初始值,然后设置为最终值)。这是我的代码和一些评论。

CGPoint originalPosition =    self.mainContainerView.contentContainerView.layer.position;
    [CATransaction lock];
    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        //Setting final value works here, but layer resets to initial position and then this line is invoked (ugly flicker effect)
        self.mainContainerView.contentContainerView.layer.position = CGPointMake(originalPosition.x, originalPosition.y + _menuOffset);
        _menuViewState = MenuViewStateOpened;
        [self.mainContainerView.contentContainerView.layer removeAllAnimations];
    }];

    _menuOffset = self.mainContainerView.menuContainerView.frame.size.height;
    CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    keyframeAnimation.path = [self getBounceCGPath];
    keyframeAnimation.keyTimes = @[@0, @(2 / 6.0), @(3 / 6.0), @(4 / 6.0), @(5 / 6.0), @1];
    keyframeAnimation.duration = 0.4;
    //Without this two lines ugly flicker appears (final value is not set, so this is workaround)
    keyframeAnimation.fillMode = kCAFillModeForwards;
    keyframeAnimation.removedOnCompletion = NO;
    //-------------------------------------------

    //This should prevent for setting final value before animation starts
    [CATransaction setDisableActions:YES];

    //Setting final value (for unknown reason this is not working, moving this line after 'addAnimation' method does not work either)
    self.mainContainerView.contentContainerView.layer.position = CGPointMake(originalPosition.x, originalPosition.y + _menuOffset);
    [self.mainContainerView.contentContainerView.layer addAnimation:keyframeAnimation
                                                             forKey:@"reveal"];
    [CATransaction commit];
    [CATransaction unlock];

1 个答案:

答案 0 :(得分:1)

我总是在添加动画之前设置新值,它工作正常。所以不要只为完成块而烦恼:

_menuOffset = self.mainContainerView.menuContainerView.frame.size.height;
self.mainContainerView.contentContainerView.layer.position = CGPointMake(originalPosition.x, originalPosition.y + _menuOffset);

CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
keyframeAnimation.path = [self getBounceCGPath];
keyframeAnimation.keyTimes = @[@0, @(2 / 6.0), @(3 / 6.0), @(4 / 6.0), @(5 / 6.0), @1];
keyframeAnimation.duration = 0.4;
keyframeAnimation.removedOnCompletion = NO;
[self.mainContainerView.contentContainerView.layer addAnimation:keyframeAnimation forKey:@"reveal"];

设置图层的新动画值应该是你要做的第一件事,除非你想要它回弹。