【发布时间】:2021-04-09 04:16:11
【问题描述】:
考虑这个简单的例子:
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 仍然直接附加到偏移修改器。这违反了我对这些修改器如何链接的理解,其中(根据this source)动画修改器适用于它需要的所有视图,直到下一个嵌套动画修改器。
【问题讨论】:
-
说实话,我不清楚你想达到什么目的。
-
@Asperi 影响父视图属性(偏移量、位置)的动画不应在子视图中触发动画。在上面的例子中,整个圆(外 + 内)应该一起移动,即使子视图(即内圆)正在执行其他动画。
-
动画由修改后的属性触发,反之则不然。因此,如果您更改可动画属性,则当前上下文动画将被激活。如果您想要独立的动画,请将它们加入到特定的不同值中。
-
@Asperi 在这种情况下将动画修改器绑定到不同的值仍然不能解决问题 - 我已经尝试过了。问题是动画修改器绑定到改变一个属性的值仍将应用于它们修改到的视图的所有其他属性,即使该属性的更改是隐式的(即,由于父级更改,它是屏幕上的全局位置它是自己的偏移量,即使孩子的本地位置根本没有改变)。
-
@roozbubu,我发现了同样的问题,见stackoverflow.com/questions/65582121/…。
标签: ios swift swiftui swiftui-animation