这是否意味着无法控制在“表单”视图内发生的动画?我在这里有一个游乐场,展示了这个问题以及发生的一切。如您所见,我在第二个动画视图上的转场被完全忽略了,由于持续时间也被忽略,我不得不手动放慢视频播放速度。
我并不是真的想要缩放转换,这只是为了证明无论我放在那里的动画都是一样的。这是预期的,还是一个错误?还是我只是做错了什么?
我还不清楚为什么VStack的动画处理方式与简单的Text字段有很大不同,而Text字段却很好地滑落了,而VStack似乎组合了.move和.opacity。
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
@State var showGoodAnimation = false
@State var showBadAnimation = false
var body: some View {
Form {
Toggle(isOn: self.$showGoodAnimation.animation(.easeInOut(duration: 1))) {Text("Yay!")}
if self.showGoodAnimation {
Text("I animate beautifully.")
}
Toggle(isOn: self.$showBadAnimation.animation(.easeInOut(duration: 1))) {Text("Boo!")}
if self.showBadAnimation {
VStack {
Text("Hi.").padding()
Text("I'm a hot mess.").padding()
}
.frame(height: 250)
.transition(.scale)
}
Text("I'm just always here.")
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
答案 0 :(得分:1)
猜测,可能前一段时间解决了这个问题,但为了那些现在反对 SwiftUI Form 之类的人的利益(就像我一样 :-))
事实证明,Forms、Lists 和(毫无疑问)其他组件故意忽略动画定制,因为它们是“更高级别”的 SwiftUI 视图组件(与 V 和 HStack 不同)。
他们这样做是因为 SwiftUI 的高级组件旨在传达语义信息并且(更实际地)在所有平台上都能很好地工作。为实现这一目标,Apple 的工程决策一直是让动画变得“简单”,但(正如观察到的)只是在本质上将其“打开”或“关闭”。
它可能是这样设计的,因为如果开发人员想要更多控制。然后,Apple 认为鼓励他们使用较低级别的组件比尝试解决他们已应用于较高级别的视图组件的优化要少得多。
无论如何,对于确定的,通过将 View 包裹在容器中并指定 .animation(nil)
修饰符(如 Asperi's SO answer here 中提到的)至少有一个逃生舱口。
为了完整起见,下面显示了一个示例;就我个人而言,我正在避免这种模式,因为我怀疑它有点像枪。
import PlaygroundSupport
import SwiftUI
struct ContentView: View {
@State var showGoodAnimation = false
@State var showBadAnimation = false
var body: some View {
Form {
Toggle(isOn: self.$showGoodAnimation.animation(.easeInOut(duration: 1))) { Text("Yay!") }
if self.showGoodAnimation {
Text("I animate beautifully.")
}
Toggle(isOn: self.$showBadAnimation.animation()) { Text("Boo!") }
VStack {
if self.showBadAnimation {
List {
Text("I animated differently").padding()
Text("But am I a footgun?").padding()
}
.transition(.asymmetric(insertion: .slide, removal: .opacity))
.animation(.easeOut(duration: 5))
}
}
.animation(nil)
.transition(.slide)
Text("I'm just always here.")
}
}
}
PlaygroundPage.current.setLiveView(ContentView())