在UIView动画期间,如何为UIView图层的子图层设置动画?

时间:2014-07-10 06:57:16

标签: ios uiview calayer uiviewanimation cabasicanimation

在视图的UIView动画中,您可以通过在UIViewAnimationOptionLayoutSubviews的options参数中包含[UIView animateWithDuration:delay:options:animations:completion:]来为其布局的子视图设置动画。但是,当它们不是某个视图的背景层时,我无法找到一种方法来设置其子图层的动画。他们只是跳到位以匹配视图的新界限。由于我使用的是图层而不是视图,我似乎必须使用Core Animation而不是UIView动画,但我不知道如何(以及何时)这样做,以便图层动画匹配直到视图动画。

这是我的基本问题。如果您想了解我想要完成的具体事情,请阅读更多内容。

我通过在视图的图层中添加CAShapeLayer来创建带有虚线边框的视图(请参阅此stackoverflow问题:Dashed line border around UIView)。我调整CAShapeLayer的路径以匹配layoutSubviews中视图的边界。

这是有效的,但有一个美容问题:当视图的边界在UIView动画中动画时(如旋转期间),虚线边框会跳转到视图的新边界,而不是平滑地动画到它因为视图动画了它的界限。也就是说,当视图动画时,虚线边框的右边部分和底部部分不会分别保持与视图的右边部分和底部部分紧密相连。 我如何从CAShapeLayer中获取虚线边框,以便在视图动画边界时为视图设置动画?

我到目前为止所做的是将CABasicAnimation附加到CAShapeLayer:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
    self.borderLayer.frame = self.bounds;

    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    [self.borderLayer addAnimation:pathAnimation forKey:nil];
}

这会导致虚线边框动画,但它没有正确的计时功能和动画持续时间来匹配视图动画。此外,有时候,我们不希望虚线边框有动画,例如,当视图首先进行布局时,边框不应该从一些旧路径动画到新的正确路径;它应该出现。

1 个答案:

答案 0 :(得分:23)

你可能已经找到了答案,但最近我也遇到了类似的问题,因为解决了这个问题,我会发布答案。

- layoutSubViews方法中,您可以使用UIView方法获取当前CAAnimation动画作为支持图层的- animationForKey:。 使用此功能,您可以实现- layoutSubviews,如:

- (void)layoutSubviews {
    [super layoutSubviews];

    // get current animation for bounds
    CAAnimation *anim = [self.layer animationForKey:@"bounds"];

    [CATransaction begin];
    if(anim) {
        // animating, apply same duration and timing function.
        [CATransaction setAnimationDuration:anim.duration];
        [CATransaction setAnimationTimingFunction:anim.timingFunction];

        CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        [self.borderLayer addAnimation:pathAnimation forKey:@"path"];
    }
    else {
        // not animating, we should disable implicit animations.
        [CATransaction disableActions];
    }

    self.borderLayer.path = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
    self.borderLayer.frame = self.bounds;
    [CATransaction commit];
}