gpt4 book ai didi

ios - SwiftUI - 在转换期间更新目标 View

转载 作者:行者123 更新时间:2023-12-05 05:59:49 24 4
gpt4 key购买 nike

我想在 SwiftUI 中使用水平滑动过渡在两个 View 之间进行过渡。问题是,一旦从网络获取数据,我还想更新目标 View 。

下面是过渡的最小示例。当按下第一个 View 上的按钮时,转换和(占位符)后台工作开始。为了获得更好的可见性,过渡速度会放慢。在第二个 View 中,我有一个 ProgressView,一旦数据可用,它应该被替换为实际 View (这里是一个 Text View )。

@main
struct MyApp: App {
@StateObject private var viewModel = ViewModel()
@State private var push = false
private let transition = AnyTransition.asymmetric(insertion: .move(edge: .trailing),
removal: .move(edge: .leading))
private let transitionAnimation = Animation.easeOut(duration: 3)

var body: some Scene {
WindowGroup {
if !push {
VStack(alignment: .center) {
HStack { Spacer() }
Spacer()

Button(action: {
push.toggle()
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.2) {
DispatchQueue.main.sync {
self.viewModel.someText = "Test ### Test ### Test ### Test ### Test ### Test ###"
}
}
}){
Text("Go")
}

Spacer()
}
.background(Color.green)
.transition(transition)
.animation(transitionAnimation)
} else {
SecondView()
.transition(transition)
.animation(transitionAnimation)
.environmentObject(viewModel)
}
}
}
}

final class ViewModel: NSObject, ObservableObject {
@Published var someText: String = ""
}

struct SecondView: View {
@EnvironmentObject var viewModel: ViewModel

var body: some View {
VStack(alignment: .center) {
HStack { Spacer() }
Spacer()

if(viewModel.someText.isEmpty) {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
} else {
Text(viewModel.someText)
}

Spacer()
}.background(Color.red)
}
}

现在的问题是 Text View 不包含在 View 转换中。我希望它与过渡一起移动(= 红色区域),但相反,它只是出现在过渡后的位置。下面的动画展示了这种效果。

enter image description here

是否可以实现Text View 的动画?需要明确的是:我知道在这种情况下我可以始终显示 Text View ,因为字符串在开头是空的。如前所述,这是我的实际 View 层次结构的大幅简化版本。我看不到省略 if-else 语句或使用 hidden 修饰符的方法。

最佳答案

只需要做几件事就可以使其正常工作。

首先,即使 someText 为空,Text 也应该存在于 View 层次结构中。您可以将它和进度指示器包装到 ZStack 中,并使用 .opacity 而不是 if/else 语句来控制文本可见性。

其次,可以根据更改的值有条件地应用动画。您应该仅在 push 变量更改时应用 transitionAnimation:

.animation(transitionAnimation, value: push)

不过有一个问题:它不会在同一变量的 if/else 分支中起作用,因为每个 .animation 语句都只存在于push 变量的一个值,它的变化不会被注意到。要解决这个问题,if/else 应该被包装到一个 Group 中,并且应该对其应用动画。

这是一个完整的解决方案:

@main
struct MyApp: App {
@StateObject private var viewModel = ViewModel()
@State private var push = false
private let transition = AnyTransition.asymmetric(insertion: .move(edge: .trailing),
removal: .move(edge: .leading))
private let transitionAnimation = Animation.easeOut(duration: 3)

var body: some Scene {
WindowGroup {
Group {
if !push {
VStack(alignment: .center) {
HStack { Spacer() }
Spacer()

Button(action: {
push.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.viewModel.someText = "Test ### Test ### Test ### Test ### Test ### Test ###"
}
}){
Text("Go")
}

Spacer()
}
.background(Color.green)
.transition(transition)
} else {
SecondView()
.transition(transition)
.environmentObject(viewModel)
}
}
.animation(transitionAnimation, value: push)
}
}
}

final class ViewModel: NSObject, ObservableObject {
@Published var someText: String = ""
}

struct SecondView: View {
@EnvironmentObject var viewModel: ViewModel

var body: some View {
VStack(alignment: .center) {
HStack { Spacer() }
Spacer()

ZStack {
if(viewModel.someText.isEmpty) {
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
}
Text(viewModel.someText)
.opacity(viewModel.someText.isEmpty ? 0.0 : 1.0)
}

Spacer()
}.background(Color.red)
}
}

关于ios - SwiftUI - 在转换期间更新目标 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67942387/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com