考虑这个简单的例子:
struct TestView: View {
@State private var enabled = false
var body: some View {
Circle()
.foregroundColor(.red)
.overlay(
Circle()
.foregroundColor(.blue)
.frame(width: 50, height: 50)
.animation(.spring())
)
.frame(width: 100, height: 100)
.offset(x: 0, y: enabled ? -50 : 50)
.animation(.easeIn(duration: 1.0))
.onTapGesture{
enabled.toggle()
}
}
}
点击生成的圆圈时会产生以下动画:
嵌套圆使用其自己的计时功能(弹簧)动画到其新的全局位置,而外圆/父视图使用其 easeInOut 计时功能动画到新的全局位置。理想情况下,如果修饰符在父视图抽象级别上工作(在这种情况下,offset
,还有类似的东西position
),所有子级都将使用父级计时函数进行动画处理。
这可能是因为 SwiftUI 渲染引擎在布局过程中为视图层次结构中所有受影响的子项计算新的全局属性,并根据附加的最具体的动画修饰符对每个属性的更改进行动画处理(即使在这种情况下,相对位置父母中的孩子不会改变)。当视图的子视图可能运行自己的复杂动画(父视图不知道也不应该知道)时,这使得做像正确翻译视图这样简单的事情变得非常困难。
我注意到的另一个怪癖是,在这个特定的示例中,在偏移修改器之前animation(nil)
添加一个修改器会破坏外圆上的动画,尽管其余部分直接附加到偏移修改器。这违反了我对这些修改器如何链接的理解,其中(根据此来源)动画修改器适用于它需要的所有视图,直到下一个嵌套动画修改器。.easeInOut