SwiftUI 延迟同步多个 SwiftUI 动画
SwiftUI synchronizing multiple SwiftUI animations with delays
我正在尝试构建一个包含多个项目的视图,这些项目应该彼此同步设置动画;例如,如果一项为 25%,则其他三项应为 50%、75% 和 100%。
仅使用 .delay(delay)
的幼稚选项一开始似乎工作得很好,但一旦我切换应用程序,不同的动画就会全部重置为完美偏移(不再有任何偏移)。
我已经尝试了一些 hacky 解决方法,包括:
- 当视图 backgrounded/restored 时切换整个动画容器;这是行不通的。 (我认为是因为即使容器不可见,容器也会与动画状态一起保存。)
- 使用
DispatchQueue.main.asyncAfter()
;这与动画没有任何不同(因为我认为这是内部动画状态本身丢失了。)
请注意,我完全没有投资于这个特定的解决方案;非常欢迎任何关于更好的方法来解决这个问题的建议。
Before switching apps
After switching apps
struct MyRepeatingItemView: View {
var delay: Double
@State
var isTranslated = false
var body: some View {
Color.red
.opacity(0.2)
.frame(width: 256, height: 256)
.scaleEffect(isTranslated ? 1 : 0.01)
.onAppear {
withAnimation(Animation.linear(duration: 4).repeatForever(autoreverses: false).delay(delay)) {
isTranslated.toggle()
}
}
}
}
struct MyRepeatingContainerView: View {
var body: some View {
ZStack {
Color.blue
.frame(width: 256, height: 2)
Color.blue
.frame(width: 2, height: 256)
MyRepeatingItemView(delay: 0.0)
MyRepeatingItemView(delay: 1.0)
MyRepeatingItemView(delay: 2.0)
MyRepeatingItemView(delay: 3.0)
}
}
}
解决不同步视图的方法是将它们全部放在一个视图中,并且该视图会同时同步所有内容。我花了一些时间来弄清楚这个模式,但这里是:
struct MyRepeatingItemView: View {
@State var isTranslated = false
var body: some View {
ZStack {
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(isTranslated ? 0 : 0.25)
.scaleEffect(isTranslated ? 1 : 0.75)
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(0.25)
.scaleEffect(isTranslated ? 0.75 : 0.5)
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(0.25)
.scaleEffect(isTranslated ? 0.5 : 0.25)
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(0.25)
.scaleEffect(isTranslated ? 0.25 : 0)
}
.onAppear {
withAnimation(Animation.linear(duration: 1).repeatForever(autoreverses: false)) {
isTranslated.toggle()
}
}
}
}
struct MyRepeatingContainerView: View {
var body: some View {
ZStack {
Color.blue
.frame(width: 256, height: 2)
Color.blue
.frame(width: 2, height: 256)
MyRepeatingItemView()
}
}
}
我正在尝试构建一个包含多个项目的视图,这些项目应该彼此同步设置动画;例如,如果一项为 25%,则其他三项应为 50%、75% 和 100%。
仅使用 .delay(delay)
的幼稚选项一开始似乎工作得很好,但一旦我切换应用程序,不同的动画就会全部重置为完美偏移(不再有任何偏移)。
我已经尝试了一些 hacky 解决方法,包括:
- 当视图 backgrounded/restored 时切换整个动画容器;这是行不通的。 (我认为是因为即使容器不可见,容器也会与动画状态一起保存。)
- 使用
DispatchQueue.main.asyncAfter()
;这与动画没有任何不同(因为我认为这是内部动画状态本身丢失了。)
请注意,我完全没有投资于这个特定的解决方案;非常欢迎任何关于更好的方法来解决这个问题的建议。
Before switching apps | After switching apps |
---|---|
struct MyRepeatingItemView: View {
var delay: Double
@State
var isTranslated = false
var body: some View {
Color.red
.opacity(0.2)
.frame(width: 256, height: 256)
.scaleEffect(isTranslated ? 1 : 0.01)
.onAppear {
withAnimation(Animation.linear(duration: 4).repeatForever(autoreverses: false).delay(delay)) {
isTranslated.toggle()
}
}
}
}
struct MyRepeatingContainerView: View {
var body: some View {
ZStack {
Color.blue
.frame(width: 256, height: 2)
Color.blue
.frame(width: 2, height: 256)
MyRepeatingItemView(delay: 0.0)
MyRepeatingItemView(delay: 1.0)
MyRepeatingItemView(delay: 2.0)
MyRepeatingItemView(delay: 3.0)
}
}
}
解决不同步视图的方法是将它们全部放在一个视图中,并且该视图会同时同步所有内容。我花了一些时间来弄清楚这个模式,但这里是:
struct MyRepeatingItemView: View {
@State var isTranslated = false
var body: some View {
ZStack {
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(isTranslated ? 0 : 0.25)
.scaleEffect(isTranslated ? 1 : 0.75)
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(0.25)
.scaleEffect(isTranslated ? 0.75 : 0.5)
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(0.25)
.scaleEffect(isTranslated ? 0.5 : 0.25)
Rectangle()
.fill(Color.red)
.frame(width: 256, height: 256)
.opacity(0.25)
.scaleEffect(isTranslated ? 0.25 : 0)
}
.onAppear {
withAnimation(Animation.linear(duration: 1).repeatForever(autoreverses: false)) {
isTranslated.toggle()
}
}
}
}
struct MyRepeatingContainerView: View {
var body: some View {
ZStack {
Color.blue
.frame(width: 256, height: 2)
Color.blue
.frame(width: 2, height: 256)
MyRepeatingItemView()
}
}
}