【问题标题】:How to dismiss multiple view with SwiftUI如何使用 SwiftUI 关闭多个视图
【发布时间】:2019-12-24 09:06:32
【问题描述】:
import SwiftUI

struct ContentView: View {
    @State var showSecond = false
    @State var showThird = false

    var body: some View {
        VStack(spacing: 50) {
            Text("FirstView")
            Button("to SecondView") {
                self.showSecond = true
            }
            .sheet(isPresented: $showSecond) {
                VStack(spacing: 50) {
                    Text("SecondView")
                    Button("to ThirdView") {
                        self.showThird = true
                    }
                    .sheet(isPresented: self.$showThird) {
                        VStack(spacing: 50) {
                            Text("ThirdView")
                            Button("back") {
                                self.showThird = false
                            }
                            Button("back to FirstView") {
                                self.showThird = false
                                self.showSecond = false
                            }
                        }
                    }
                    Button("back") {
                        self.showSecond = false
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

上面的代码从FirstView过渡到SecondView,从SecondView过渡到ThirdView。而SecondView 和ThirdView 中的“返回”按钮正常返回上一屏。

但是,如果您在 ThirdView 中点击“返回 FirstView”按钮,将显示 SecondView 而不会返回 FirstView。而且这个操作之后,当你点击SecondView的“返回”按钮时,它并没有返回到FirstView。

如何从 ThirdView 直接返回到 FirstView?


2020 年 2 月 19 日添加

我已经根据答案添加了解决方案代码。

解决方案 1:基于 Asperi 的 A 计划。

struct ContentView: View {
    @State var showSecond = false
    @State var showThird = false

    var body: some View {
        VStack(spacing: 50) {
            Text("FirstView")
            Button("to SecondView") {
                self.showSecond = true
            }
            .sheet(isPresented: $showSecond) {
                VStack(spacing: 50) {
                    Text("SecondView")
                    Button("to ThirdView") {
                        self.showThird = true
                    }
                    .sheet(isPresented: self.$showThird) {
                        VStack(spacing: 50) {
                            Text("ThirdView")
                            Button("back") {
                                self.showThird = false
                            }
                            Button("back to FirstView") {
                                DispatchQueue.main.async {
                                    self.showThird = false
                                    DispatchQueue.main.async {
                                        self.showSecond = false
                                    }
                                }
                            }
                        }
                    }
                    Button("back") {
                        self.showSecond = false
                    }
                }
            }
        }
    }
}

解决方案 2:基于 Asperi 的 B 计划。

struct ContentView: View {
    @State var showSecond = false
    @State var showThird = false
    @State var backToFirst = false

    var body: some View {
        VStack(spacing: 50) {
            Text("FirstView")
            Button("to SecondView") {
                self.showSecond = true
            }
            .sheet(isPresented: $showSecond) {
                VStack(spacing: 50) {
                    Text("SecondView")
                    Button("to ThirdView") {
                        self.showThird = true
                    }
                    .sheet(isPresented: self.$showThird, onDismiss: {
                        if self.backToFirst {
                            self.showSecond = false
                        }
                    }) {
                        VStack(spacing: 50) {
                            Text("ThirdView")
                            Button("back") {
                                self.showThird = false
                                self.backToFirst = false
                            }
                            Button("back to FirstView") {
                                self.showThird = false
                                self.backToFirst = true
                            }
                        }
                    }
                    Button("back") {
                        self.showSecond = false
                    }
                }
            }
        }
    }
}

解决方案 3:根据 Joseph 的建议。

struct ContentView: View {
    @State var showSecond = false
    @State var showThird = false

    var body: some View {
        GeometryReader { geometry in
            ZStack {
                VStack(spacing: 50) {
                    Text("FirstView")
                    Button("to SecondView") {
                        self.showSecond = true
                    }
                }
                .frame(width: geometry.size.width, height: geometry.size.height)
                .background(Rectangle().foregroundColor(.white))
                if self.showSecond {
                    VStack(spacing: 50) {
                        Text("SecondView")
                        Button("to ThirdView") {
                            self.showThird = true
                        }
                        Button("back") {
                            self.showSecond = false
                        }
                    }
                    .frame(width: geometry.size.width, height: geometry.size.height)
                    .background(Rectangle().foregroundColor(.white))
                    if self.showThird {
                        VStack(spacing: 50) {
                            Text("ThirdView")
                            Button("back") {
                                self.showThird = false
                            }
                            Button("back to FirstView") {
                                self.showThird = false
                                self.showSecond = false
                            }
                        }
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .background(Rectangle().foregroundColor(.white))
                    }
                }
            }
        }
    }
}

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    目前直接没有办法(而且 IMO 永远不会 - 这是两个模态会话)...我发现了两种可能值得考虑的方法:

    A.从一个地方顺序关闭

    Button("back to FirstView") {
        DispatchQueue.main.async {
            self.showThird = false
            DispatchQueue.main.async {
                self.showSecond = false
            }
        }
    }
    

    B.从不同的地方顺序关闭

    .sheet(isPresented: self.$showThird, onDismiss: {
        self.showSecond = false // with some additional condition for forced back
    })...
    
    ...
    
    Button("back to FirstView") {
        self.showThird = false
    }
    

    【讨论】:

    • 感谢您的建议!我已经尝试过你的建议。 A计划没有效果。但是,当我使用“DispatchQueue.main.asyncAfter (deadline: .now () + 0.01)”而不是“DispatchQueue.main.async”时,它现在按建议工作。 B计划按建议进行。当我使用这个计划时,我需要在“.onDismiss”处添加一个可以确定是否返回FirstView的新状态变量。无论如何,这两个计划都是逐步过渡到返回FirstView,而不是直接过渡。我想等待对方的解决方案。
    • 我又检查了一遍。 planA 使用如图所示的代码。当我之前检查它时,我在设置 showThird 之前省略了 DispatchQueue。我已根据此建议向问题区域添加了代码。
    【解决方案2】:

    另一个/cough/“解决方案” - 可能是稍微不同的场景 - 但无论如何:

    struct ContentView: View {
        var body: some View {
            NavigationView {
                NavigationLink(destination: SecondView()) {
                    Text("Show Second View")
                        .font(.largeTitle)
                }
            }
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }
    
    struct SecondView: View {
        @Environment(\.presentationMode) var presentationMode
    
        @State private var showModal = false
    
        var body: some View {
            GeometryReader { geometry in
                ZStack {
                    Rectangle()
                        .foregroundColor(.gray)
                        .frame(width: geometry.size.width, height: geometry.size.height)
                    Button(action: {
                        withAnimation {
                            self.showModal.toggle()
                        }
                    }) {
                        Text("Show Third View")
                            .font(.largeTitle)
                            .foregroundColor(.white)
                    }
    
                    if self.showModal {
                        VStack {
                            Button(action: {
                                self.presentationMode.wrappedValue.dismiss()
                            } ) {
                                Text("Show First View")
                                    .font(.largeTitle)
                                    .foregroundColor(.white)
                            }
                        }
                            .frame(width: geometry.size.width, height: geometry.size.height)
                            .background(Rectangle().foregroundColor(.orange))
                            .transition(.move(edge: .trailing))
                    }
                }
                .frame(width: geometry.size.width, height: geometry.size.height)
            }
        }
    }
    

    【讨论】:

    • Z-stacking 多个基于@State 布尔值渲染的动画视图可能是一种使合成展开后“深度”连续几层的方法。它并不完全优雅,但是......是的
    • 感谢您的建议!您关于使用 zstack 覆盖视图的建议非常有帮助。如果我们不关心使用工作表为模态转换设置动画,此方法非常有效。我已根据此建议将代码添加到问题区域。
    【解决方案3】:

    Asperi 的解决方案适用于同时关闭两个屏幕,但不适用于更多屏幕。在这种情况下,我们需要在两种方法中添加DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)),如下所示:

    self.showFourth = false
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
        self.showThird = false
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
            self.showSecond = false
        }
    }
    

    .milliseconds(200) 还不够。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-04
      • 2021-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多