【问题标题】:How do you animate the sublayers of the layer of a UIView during a UIView animation?在 UIView 动画期间如何为 UIView 层的子层设置动画?
【发布时间】:2014-08-31 10:59:40
【问题描述】:

在视图的 UIView 动画中,您可以通过在 [UIView animateWithDuration:delay:options:animations:completion:] 的选项参数中包含 UIViewAnimationOptionLayoutSubviews 来为其 子视图 设置动画。但是,当它们不是某个视图的支持层时,我无法找到一种方法来设置其 子层 的动画;他们只会跳到位以匹配视图的新边界。由于我使用的是图层而不是视图,因此似乎我必须使用 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];
}

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

【问题讨论】:

    标签: ios uiview calayer uiviewanimation cabasicanimation


    【解决方案1】:

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

    - layoutSubViews方法中,你可以通过- animationForKey:方法获取当前UIView动画作为backing layer的CAAnimation。 使用这个,你可以实现- 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];
    }
    

    【讨论】:

    • 我不得不使用“position”属性来获取animationForKey,但除此之外它对我来说非常有用!
    • 谢谢,但我应该提一下,这不适用于动画方法 [UIView animateWithDuration: usingSpringWithDamping: initialSpringVelocity: options: animations: completion:]
    • @Eric 你也可以使用bounds.size。一个快速断点和检查 animationKeys 告诉我有 3 个动画正在进行 [position, bounds.size, bounds.origin]
    • @rintaro,如果我的 UIView 动画代码没有明确的关键路径可以参考,比如在UIView.animationWithDuration: 中调用layoutIfNeeded(),你知道这种情况下的解决方案吗?
    • 如果您尝试在键盘显示/隐藏动画旁边进行动画处理,这将不起作用...(持续时间和计时功能不同)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    相关资源
    最近更新 更多