见 How to manage CALayer animations throughout a hierarchy关于如何同步父子层动画的后续问题。
这是一个设计问题,涉及在 View 层次结构的不同层次上运行相关动画以响应层次结构上的动画。
我有一个容器 Controller ,它有任意数量的子 Controller 。父 Controller 在屏幕上组织这些内容,并且在各个点需要更改其 subview 的大小和位置。
我正在尝试为这些 subview 中的每一个设置动画,以将其大小/形状/位置从原始起点过渡到目的地。带有一些基本动画的基本第一次通过开始完成工作。
由于某些被调整大小的 View 也应该在 View 的内容上执行动画,事情变得更加复杂。想象一个内容居中的 subview 。随着 child 缩小或扩大,居中的内容应与外部动画一起制作动画,以补偿边界变化,从而使内容保持居中。
更复杂的是,我还为每个需要与子动画一起制作动画的 subview 设置了一个 mask 层。我还有一些手势不需要使用动画来进行转换 - 所以我需要一种方法来制作整个 View /图层树的动画,有时不需要。
所有这一切都为我提供了一个架构,其中我有类似以下的内容
ContainerViewController.view
-> auxiliary and decorative views
-> WrapperView (multiple)
----> mask layer
-> Child controller view
-> subviews & layers
现在我的问题实际上是可维护性问题。我可以使用显式或隐式动画为这些部分设置动画。我需要弄清楚的是,确保所有正在完成的动画都使用相同的持续时间和计时函数完成的最佳方法是什么。目前,我触发了很多这些关闭属性的更改。在某些情况下,属性更改来自 layoutSubviews(由 setNeedsLayout 触发)。
那么,设置这些动画的最佳策略是什么,尤其是显式动画。我能做的最好的事情是从 CATransaction 中获取值(value)吗?我担心并不是每个属性都需要在每种情况下都进行动画处理(例如在辅助 View 中)——我已经在打开/关闭 setDisableActions 以强制/拒绝某些属性动画。
是否应该使用 CATransaction 来触发显式 View 动画的设置?如何将为 UIView 动画指定的参数绑定(bind)到将用于底层图层的参数?下面的代码似乎完成了工作,但看起来真的很难看。
-(void) animateForReasonenum AnimationReason) animationReason
animationsvoid(^)()) animationBlock completionvoid(^)(BOOL)) completionBlock {
const auto animationDuration = 3.0; // make this long to be noticeable!
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationOptionLayoutSubviews
animations:^{
[CATransaction begin];
[CATransaction setAnimationDuration:animationDuration];
animationBlock();
[CATransaction commit];
}completion:completionBlock];
}
我认为 UIViewControllerTransitionCoordinator 已经过时了,因为我需要制作所有这些动画来响应用户操作,而不仅仅是外部事物,如旋转或帧更改。
Best Answer-推荐答案 strong>
有几个选项可以考虑:
- 对于 UIView 过渡,您可以传递
UIViewAnimationOptionLayoutSubviews 选项。这将在您刚刚更改其框架的 View 上调用 layoutSubviews 之前和之后 subview 之间的更改动画。
- 您可以在
UIView 上覆盖 setBounds: 或 setFrame: 而不是使用 layoutSubviews 和CALayer 子类。这样,如果在动画 block 中调用它们, subview 将与父 View 一起动画。如果它们没有在动画 block 中调用,它们会立即更新。
My fear is that not every property needs to be animated in every case (like in the auxiliary views) - I already am flipping setDisableActions on/off to force/deny some property animations.
一般来说,如果你想要它动画,把它放在一个动画 block 中,如果你不这样做,就不要。显然,它可能会变得比这更复杂,这就是为什么 Apple 有时会有一个带有 animated 参数的 setter(如 setSelected:animated: )。
如果您有有时开启有时关闭的属性,请自行遵循此模式。一种可能的实现方式:
- (void) setNumberOfWidgetsint)widgetCount animatedBOOL)animated {
BOOL oldAnimationValue = [UIView areAnimationsEnabled];
if (!animated) {
[UIView setAnimationsEnabled:NO];
}
// a related property which may or may not cause an animation
self.someOtherProperty = someValue;
if (!animated) {
[UIView setAnimationsEnabledldAnimationValue];
}
}
My question is really one of maintainability.
是的,听起来您正在考虑某种巨型对象,它可以为您管理所有动画可能性。抵制这种诱惑。让每个 View 负责为其自己的 subview 设置动画,并告诉一个 View (不要让它问)是否应该为这些更改设置动画。
I think that UIViewControllerTransitionCoordinator is out because I need to do all of these animations in response to user actions, not just external things, like rotations or frame changes.
是的,没错。不要为此使用 UIViewControllerTransitionCoordinator 。
关于ios - 如何在复杂的层次结构上下同步 CALayer 和 UIView 动画,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/26879254/
|