SwiftUI-关闭工作表视图,不仅关闭视图

问题描述 投票:1回答:2

我想实现该功能。就像来自Apple的“查找”视图一样。

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

enter image description here

我尝试实现此功能。

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

enter image description here

这是我的代码。

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")
            }
        )
    }
}

我如何实现此功能? :)请帮助我,谢谢。 :)

ios swift navigation swiftui dismiss
2个回答
0
投票

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

我刚刚学习的一种方法是使用@Binding变量。这可能不是最佳解决方案,但它确实有效!

所以您的$isShowSheet中有这个ContentView。通过在NavView中声明一个变量,将该对象传递到NavView结构。

ContentView

    .....

    }.sheet(isPresented: $isShowSheet) {
        NavView(isShowSheet: self.$isShowSheet)
    }

NavView

struct NavView: View {
    @Binding var isShowSheet: Bool

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

最后,对您的subView做同样的事情。

NavSubView

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")
            }
        )
    }
}

现在您可以看到,您只需要向该isShowSheet绑定变量-false发送一个新信号。

self.isShowSheet = false

Voila!

enter image description here


0
投票

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

这里是可能的方法(已通过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 }
    }
}

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

    }.sheet(isPresented: $isShowSheet) {
        NavView()
           .environment(\.showingSheet, self.$isShowSheet)
    }

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

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

    var body: some View {
        Text("Hello")
        .navigationBarItems(trailing:
            Button("Done") {
                self.showingSheet?.wrappedValue = false
            }
        )
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.