Showing and hiding views

在 SwiftUI 中,有许多展示视图的方法,而其中一种最基本的方式就是使用 sheet:在现有视图上展示一个新视图。在 iOS 上,这种展示方式会自动呈现为类似卡片的形式,当前视图稍微向后滑动,而新视图则动画地从底部滑入。

与警报 (alert) 类似,sheet 的展示并不是通过代码直接调用 mySheet.present() 等方法来完成的,而是通过定义一个条件,当条件为 true 时,sheet 被展示;当条件为 false 时,sheet 被关闭。

基本实现

我们从一个简单的例子开始,展示如何通过 sheet 在一个视图中展示另一个视图。首先,创建我们想要在 sheet 中显示的视图:


struct SecondView: View {
    var body: some View {
        Text("Second View")
    }
}

这只是一个简单的视图,SecondView 不需要知道自己会在一个 sheet 中展示。

接下来,我们在主视图中创建一个按钮,点击该按钮后展示 SecondView


struct ContentView: View { 
    var body: some View {
        Button("Show Sheet") {
            // show the sheet
        }
    }
}


为了让这个按钮能够展示 sheet,我们需要完成以下四个步骤:

步骤 1:创建一个状态来跟踪 sheet 是否展示

我们可以使用一个布尔值来标记当前是否展示 sheet。将以下属性添加到 ContentView


@State private var showingSheet = false

步骤 2:在按钮点击时切换状态

我们需要在按钮点击时切换 showingSheet 的值。替换掉注释部分,代码变为:


showingSheet.toggle()

步骤 3:将 sheet 附加到视图层级

接下来,我们需要将 sheet 附加到视图层级上。类似于警报使用 isPresented 绑定状态属性,我们可以使用 sheet(isPresented:) 来实现:


.sheet(isPresented: $showingSheet) {
    // contents of the sheet
}

步骤 4:指定 sheet 的内容

我们知道,sheet 的内容就是我们刚才创建的 SecondView。所以在 sheet 的闭包中,我们创建并展示一个 SecondView() 实例:

struct ContentView: View {
    @State private var showingSheet = false

    var body: some View {
        Button("Show Sheet") {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            SecondView()
        }
    }
}


运行程序后,你将能够点击按钮,在底部滑动显示 SecondView,并且可以通过拖动来关闭这个 sheet。

传递数据到 sheet

如果你希望在 SecondView 中显示一些动态内容,可以给它传递数据。例如,SecondView 需要显示一个名字:


struct SecondView: View {
    let name: String

    var body: some View {
        Text("Hello, \(name)!")
    }
}

现在,直接使用 SecondView() 在 sheet 中展示是不行的,因为我们需要为它传递一个名字。你可以这样传递数据:

.sheet(isPresented: $showingSheet) {
    SecondView(name: "@twostraws")
}


这将使得 SecondView 显示 “Hello, @twostraws”。

自动类型检查

Swift 的类型系统非常强大,它会确保你传递给 SecondView 的数据类型是正确的。如果你在没有传递 name 时尝试使用 SecondView(),编译器会直接报错,确保我们没有遗漏必要的参数。

编程方式关闭 sheet

到目前为止,用户可以通过向下滑动来关闭 sheet。但有时候,你可能希望通过代码来关闭 sheet,比如点击按钮时自动关闭。

要实现这一点,我们需要使用 @Environment 属性包装器。这个包装器让我们能够访问外部环境提供的值。例如,是否使用暗黑模式、字体大小的设置等等。在这里,我们将利用它来获取用于关闭视图的方法。

为了实现程序化关闭,我们需要在 SecondView 中添加以下代码:


@Environment(\.dismiss) var dismiss

然后,将 SecondView 中的文本视图替换为一个按钮,点击时关闭当前视图:

Button("Dismiss") {
    dismiss()
}

现在,当你点击按钮时,sheet 将会被关闭。

总结

通过使用 sheet 和 @State,你可以轻松地在 SwiftUI 中展示和关闭视图。同时,通过 @Environment(.dismiss) 可以程序化地关闭视图,提供了更灵活的用户交互方式。



Review after registration

login page