SwiftUI - 如何关闭工作表视图,同时关闭该视图

Jer*_*Lee 10 navigation dismiss ios swift swiftui

我要实现的功能。比如,来自 Apple 的“Look up”视图。

我的目标是当表单视图通过导航推送另一个视图时,用户可以点击导航项按钮来关闭表单视图。就像,这个下面的gif。

在此处输入图片说明

我尝试实现这个功能。

我发现一个问题是当用户点击“完成”按钮时。该应用程序不会关闭工作表视图。它只会将视图弹出到父视图。就像,这个下面的gif。

在此处输入图片说明

这是我的代码。

import SwiftUI

struct ContentView: View {
    @State var isShowSheet = false
    var body: some View {
        Button(action: {
            self.isShowSheet.toggle()
        }) {
            Text("Tap to show the sheet")
        }.sheet(isPresented: $isShowSheet) {
            NavView()
        }
    }
}

struct NavView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: NavSubView()) {
                Text("Enter Sub View")
            }
        } .navigationViewStyle(StackNavigationViewStyle())
    }
}

struct NavSubView: View {
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        Text("Hello")
        .navigationBarItems(trailing:
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }){
                Text("Done")
            }
        )
    }
}

Run Code Online (Sandbox Code Playgroud)

我是如何实现这个功能的?:) 请帮帮我,谢谢。:)

Asp*_*eri 16

由于工作表中的导航可能足够长并且关闭不能在所有导航子视图中,我更喜欢使用环境来仅在需要的地方指定关闭功能,而不是通过所有导航堆栈传递绑定。

这是可能的方法(使用 Xcode 11.2 / iOS 13.2 测试)

1)定义环境键来存储工作表状态

struct ShowingSheetKey: EnvironmentKey {
    static let defaultValue: Binding<Bool>? = nil
}

extension EnvironmentValues {
    var showingSheet: Binding<Bool>? {
        get { self[ShowingSheetKey.self] }
        set { self[ShowingSheetKey.self] = newValue }
    }
}
Run Code Online (Sandbox Code Playgroud)

2) 将此环境值设置为工作表内容的根目录,以便在声明时可在任何子视图中使用

    }.sheet(isPresented: $isShowSheet) {
        NavView()
           .environment(\.showingSheet, self.$isShowSheet)
    }
Run Code Online (Sandbox Code Playgroud)

3)仅在将要使用的子视图中声明和使用环境值

struct NavSubView: View {
    @Environment(\.showingSheet) var showingSheet

    var body: some View {
        Text("Hello")
        .navigationBarItems(trailing:
            Button("Done") {
                self.showingSheet?.wrappedValue = false
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)


Gle*_*enn 7

我从来没有尝试过 SwiftUI,但我来自 UIKit + RxSwift,所以我有点知道绑定是如何工作的。我从 SwiftUI 教程中阅读了很多示例代码,您关闭模态的方式实际上是正确的,但显然不适用于导航堆栈。

我刚刚学到的一种方法是使用@Bindingvar。这可能不是最好的解决方案,但它奏效了!

所以你$isShowSheetContentView. 通过NavView在该中声明一个变量将该对象传递给您的结构NavView

内容视图

    .....

    }.sheet(isPresented: $isShowSheet) {
        NavView(isShowSheet: self.$isShowSheet)
    }
Run Code Online (Sandbox Code Playgroud)

导航视图

struct NavView: View {
    @Binding var isShowSheet: Bool

    var body: some View {
        NavigationView {
            NavigationLink(destination: NavSubView(isShowSheet: self.$isShowSheet)) {
                Text("Enter Sub View")
            }
        } .navigationViewStyle(StackNavigationViewStyle())
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,对你的子视图做同样的事情。

导航子视图

struct NavSubView: View {
    @Environment(\.presentationMode) var presentationMode

    @Binding var isShowSheet: Bool

    var body: some View {
        Text("Hello")
        .navigationBarItems(trailing:
            Button(action: {
                //self.presentationMode.projectedValue.wrappedValue.dismiss()
                self.isShowSheet = false
            }){
                Text("Done")
            }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

现在如您所见,您只需要向该isShowSheet绑定 var -发送一个新信号false

self.isShowSheet = false

瞧!

在此处输入图片说明