代码之家  ›  专栏  ›  技术社区  ›  Ben Gottlieb

动画期间的布局视图?

  •  13
  • Ben Gottlieb  · 技术社区  · 14 年前

    我有一个 UIView 有一堆子视图,所有子视图都使用 layoutSubviews . 当 view 调整了大小,相对位置都改变了。我希望这些重新计算发生在动画调整(使用+ [UIView beginAnimations:] 电话)这似乎没有发生。有什么想法吗?

    4 回复  |  直到 8 年前
        1
  •  24
  •   tc.    14 年前

    假设:您希望有多个动画步骤(即位置不会随帧大小线性变化)。

    这对于一个“标准”的uiview动画是不可能的。为什么?帧/边界仅设置一次。

    Core Animation 有三层树:

    • 这个 模型树 是你的应用程序认为的地方。
    • 这个 演示树 大约是屏幕上显示的内容。
    • 这个 渲染树 基本上就是核心动画的合成。

    uiview是一个围绕模型层的(有点薄)包装器。在uiview动画期间,核心动画更新演示/渲染树-模型树表示动画的端点。结果是,您的代码可以(在大多数情况下)将动画视为即时的-将视图从A移动到B会立即将其移动到B;更改只是对用户进行动画处理。

    对于Calayer/CaAnimation,您可以直接做一些更复杂的事情,但我没有做过太多的研究。

    可以使用-[uiview setAnimationDidstopSelector:]将多个动画链接在一起。(您也可以尝试将多个动画与setAnimationDelay一起使用,但我不确定同一属性上的多个动画会发生什么情况;您可能会遇到setAnimationBeginsFromCurrentState:。)

    如果您真的想要细粒度的控制,caDisplayLink(OS 3.1+)是一个计时器,在每次屏幕刷新后都会触发它。回退选项(用于3.0支持)是使用30/60Hz左右的nstimer。

        2
  •  14
  •   quentinadam    10 年前

    完成@grizzlynetch's anwer,您可以设置 UIViewAnimationOptionLayoutSubviews 动画选项,因此不需要调用 layoutIfNeeded :

    -(void)someMethod{
        double duration = ...;
        [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
            self.frame = ...;
        } completion:nil];
    }
    
        3
  •  13
  •   JakubKnejzlik    12 年前

    我知道这是一个古老的问题,但这段代码对我来说非常适用(适用于您更改帧的例子)。

    -(void)layoutSubviews{
         [super layoutSubviews];
         // layout your subviews here, or whatever
    }
    
    -(void)someMethod{
        double duration=...;
        [UIView animateWithDuration:duration animations:^{
            self.frame = ...;
            [self layoutIfNeeded];
        }];
    }
    

    当然,您可以从另一个对象调用这个方法。“技巧”是调用layoutifneeded(或者直接调用layoutSubview——同样的,如果更改了setNeedsLayout被调用的帧)。

    作为TC。很好地解释了“层树”,您只需强制表示层显示带有动画的模型层的最后阶段。

    这种方法的优点是可以控制帧/边界何时更改以及何时更改为即时更改。

    希望这能帮助别人:)。

        4
  •  5
  •   Ben Gottlieb    14 年前

    为完整性过账。感谢TC。为了解释我想做的,确切地说,是不支持核心动画。

    我最终想出了一个合理的解决办法。而不是在-layoutSubview中布局子视图,而是在-setbounds中这样做:。然后,当我在uiview+beginimations:block中包装一个-setbounds:call时,这些定位调用也会被动画化,最终的结果是所有东西都会正确地动画化到它应该在的地方。