SwiftUI极简教程14:ModalView模态弹窗使用

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

前言:

当写这章的时候,发现以前还是关于这块内容的“高级用法”,但想了想,还是先不写那么深入,担心扩充起来内容太多,而且难以消化,就只罗列了简单的使用方法。

之后的章节中,会考虑逐渐深入下去,当讲完了SwiftUI基础功能的使用方法,后面也会考虑出一些实战项目的案例,让SwiftUI爱好者能够真正地写项目。

今日职言:努力工作,尽情玩乐。

在本章中,你将学会使用模态弹窗完成页面跳转、自定义返回。

在上一章中,我们学习了使用NavigationView导航栏进行页面的跳转,这是常见的页面跳转的一种方式。

而另一种打开新页面的方式在iPhone中也很常见,就是从底部向上弹出一个新页面。

230.png

我们可以看到,这个页面又不完全是“进入”了一个新页面,它允许用户向下滑动关闭页面,这无疑大大增强了用户体验。

这时候给用户的感觉就是没有“打断”或者“干扰”用户的操作,并且完成了用户想做的事情。

本章节将分成3个部分讲解。

1、基于模态弹窗的页面跳转;

2、模态弹窗的自定义返回;

3、Alerts警告弹窗;

好了,说了那么多,我们开始吧。

第一部分:基于模态弹窗的页面跳转

首先,我们先创建一个新项目,命名为SwiftUIModalView。

231.png

我们尝试下简单的模态弹窗的跳转。

比如,我们在第一个页面创建一个按钮,当我们点击这个按钮时,打开一个模态弹窗页面。

如何创建按钮,可以了解下之前的文章。

创建按钮的代码如下:

//按钮
Button(action: {
    // 点击按钮跳转打开模态弹窗
}) {
    // 按钮样式
    Text("打开模态弹窗")
        .font(.system(size: 14))
        .frame(minWidth: 0, maxWidth: .infinity)
        .padding()
        .foregroundColor(.white)
        .background(Color(red: 51 / 255, green: 51 / 255, blue: 51 / 255))
        .cornerRadius(5)
        .padding(.horizontal, 20)

}
复制代码

232.png

然后,我们需要再创建一个新的页面,方便我们实现从第一个页面点击按钮,以模态弹窗的方式打开第二个页面。

这里,我们基于上一章的内容,创建一个页面叫做DetailView。

在DetailView我们就放个文字简单说明下。

// 详情页
struct DetailView: View {
    var body: some View {
        Text("这是一个新页面")
    }
}
复制代码

233.png

接下来,我们实现下使用模态弹窗的跳转方法。

.sheet(isPresented: $showDetailView) { 
    //要跳转的页面
 }
复制代码

模态弹窗的方法很简单,使用.sheet修饰符。

isPresented是模态弹窗的触发条件,需要用$绑定一个操作,我们通常定义一个布尔值,它的初始状态为false。

@State var showDetailView = false
复制代码

当我们在第一个页面点击按钮时,按钮的操作就把这个布尔值变成true,那么就可以同时触发.sheet打开模态弹窗。

这里我们定义了一个叫做showDetailView的参数,它是bool类型,而且初始值为false。

当我们点击按钮时,showDetailView切换状态。

self.showDetailView.toggle()
复制代码

234.png

我们点击模拟器上的Preview试下效果。

点击按钮后,我们可以看到系统打开了我们定义好的模态弹窗页面DetailView了。

完整代码如下:

import SwiftUI

struct ContentView: View {

    @State var showDetailView = false

    var body: some View {

        // 按钮
        Button(action: {
            // 点击按钮跳转打开模态弹窗
            self.showDetailView.toggle()
        }) {
            // 按钮样式
            Text("打开模态弹窗")
                .font(.system(size: 14))
                .frame(minWidth: 0, maxWidth: .infinity)
                .padding()
                .foregroundColor(.white)
                .background(Color(red: 51 / 255, green: 51 / 255, blue: 51 / 255))
                .cornerRadius(5)
                .padding(.horizontal, 20)
        }
        .sheet(isPresented: $showDetailView) {
            DetailView()
        }
    }
}

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

// 详情页
struct DetailView: View {
    var body: some View {
        Text("这是一个新页面")
    }
}
复制代码

235.png

第二部分:模态弹窗的自定义返回

在DetailView页面里,我们可以通过向下拖动页面,实现关闭页面的效果。

我们也可以尝试给DetailView加上一个关闭按钮,当我们点击关闭按钮时,也关闭这个页面。

还记得上一章我们学习过的NavigationView导航栏吗?我们可以给DetailView内容加上导航,然后导航右边加一个按钮操作。

// 详情页
struct DetailView: View {

    var body: some View {

        NavigationView {

            //主体内容
            Text("这是一个新页面")
                .navigationBarItems(trailing: Button(action: {
                    // 点击按钮关闭弹窗
                }) {
                    Image(systemName: "chevron.down.circle.fill")
                        .foregroundColor(.gray)
                }
            )
        }
    }
}
复制代码

236.png

好了,我们看到在DetailView导航栏右上角创建了一个新按钮。

那么接下来,我们要实现点击按钮,关闭弹窗。

这里我们有两种方法。

方法1:

和上一章NavigationView导航栏一样,创建一个环境变量:

@Environment(\.presentationMode) var presentationMode
复制代码

然后当我们点击按钮时,调用它的函数方法。

self.presentationMode.wrappedValue.dismiss()
复制代码

点击模拟器的Preview,我们发现实现了点击操作,关闭当前的模态弹窗页面。

完整代码如下:

// 详情页
struct DetailView: View {

    //定义环境变量
    @Environment(\.presentationMode) var presentationMode

    var body: some View {

        NavigationView {

            //主体内容
            Text("这是一个新页面")
                .navigationBarItems(trailing: Button(action: {
                    // 点击按钮关闭弹窗
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Image(systemName: "chevron.down.circle.fill")
                        .foregroundColor(.gray)
                }
            )
        }
    }
}
复制代码

237.png

方法2:

也是之前的章节学习过 State状态和Binding绑定的使用。

我们可以在DetailView页面用@Binding绑定第一个页面创建的showDetailView布尔值。

//绑定参数
@Binding var showDetailView: Bool
复制代码

然后在DetailView页面,点击按钮操作时,将showDetailView的值切换。

self.showDetailView.toggle()
复制代码

最后在主页中.sheet跳转的目标页面绑定参数回来。

.sheet(isPresented: $showDetailView) {
    DetailView(showDetailView: $showDetailView)
}
复制代码

这样,我们也可以实现页面的返回操作。

DetailView页面完整代码如下:

// 详情页
struct DetailView: View {

    //绑定参数
    @Binding var showDetailView: Bool

    var body: some View {

        NavigationView {

            //主体内容
            Text("这是一个新页面")
                .navigationBarItems(trailing: Button(action: {
                    // 点击按钮关闭弹窗
                    self.showDetailView.toggle()
                }) {
                    Image(systemName: "chevron.down.circle.fill")
                        .foregroundColor(.gray)
                }
            )
        }
    }
}
复制代码

238.png

那么两种方法有什么不同呢?

第一种方法简单来说,是“撤销”原有的操作。

而第二种绑定的方式,是反向传递参数值给到第一个页面。

两种方式各有好处,第二种方法的好处是如果第二个页面返回的时候需要带参数值回来,那么我们可以通过绑定的方式将DetailView的值给回到第一个页面。

第三部分:Alerts警告弹窗

在模态弹窗中,还有一种类型叫做Alerts警告弹窗,也属于模态弹窗的一种。

我们在App也经常见过它,当我们确定要付款时,或者触发到有风险的操作时,系统就会打开Alerts警告弹窗。

Alerts警告弹窗一种二次确认的弹窗,常用于系统风险提醒、是否立即执行等场景。

239.png

创建警告弹窗的方法和创建一般的模态弹窗方法一样,只是参数不一样。

.alert(isPresented: $showAlert) {
    //Alerts结构体
}
复制代码

我们还是使用isPresented触发,我们定义一个变量showAlert的状态,初始状态是false。

@State var showAlert = false
复制代码

与创建标准模态弹窗不同的是,.alert里面的内容是Alerts结构体,也就是标准的警告弹窗。

我们使用Alert结构体来创建警告弹窗。

Alert(title: Text("这是弹窗标题"), message: Text("这是弹窗的内容"), primaryButton: .default(Text("确定")), secondaryButton: .cancel(Text("取消")))
复制代码

基本了解了警告弹窗的用法,让我们实操试试吧。

我们把DetailView页面的文字改成“打开警告弹窗”,然后把它变成按钮的形式。

以便于我们点击文字按钮,实现打开警告弹窗的效果。

//主体内容
    Button(action: {
        // 点击按钮打开警告弹窗

        }) {
            Text("打开警告弹窗")
        }
复制代码

240.png

然后我们将警告弹窗的方法写到DetailView页面里面,方法和主页中.sheet的方法类似。

先定义一个变量showAlert,初始值为false,当按钮点击的时候,showAlert的状态切换。

在Text按钮外边(注意位置),使用.alert的创建一个警告弹窗,然后在警告弹窗内容里填充Alerts结构体代码。

这样就完成了Alerts警告弹窗的创建。

DetailView完整代码如下:

// 详情页
struct DetailView: View {

    // 绑定参数
    @Binding var showDetailView: Bool
    @State var showAlert = false

    var body: some View {

        NavigationView {

            // 主体内容
            Button(action: {
                // 点击按钮打开警告弹窗
                self.showAlert.toggle()
            }) {
                Text("打开警告弹窗")
            }
            .alert(isPresented: $showAlert) {
                //Alerts结构体
                Alert(title: Text("这是弹窗标题"), message: Text("这是弹窗的内容"), primaryButton: .default(Text("确定")), secondaryButton: .cancel(Text("取消")))
            }
            
            
            .navigationBarItems(trailing: Button(action: {
                // 点击按钮关闭弹窗
                self.showDetailView.toggle()
            }) {
                Image(systemName: "chevron.down.circle.fill")
                    .foregroundColor(.gray)
            }
            )
        }
    }
}
复制代码

241.png

快来动手试试吧!

如果本专栏对你有帮助,不妨点赞、评论、关注~

猜你喜欢

转载自juejin.im/post/7086249115083866120