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

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

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


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


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

image.png

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

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

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


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

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

3、Alerts警告弹窗;


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


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


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

image.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)
}


image.png

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

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

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


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


image.png


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


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


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

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


@State var showDetailView = false
复制代码


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

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

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


self.showDetailView.toggle()


image.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("这是一个新页面")
    }
}


image.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)
                }
            )
        }
    }
}


image.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)
                }
            )
        }
    }
}


image.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)
                }
            )
        }
    }
}


image.png

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

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

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

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


第三部分:Alerts警告弹窗


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

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

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

image.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("打开警告弹窗")
        }

image.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)
            }
            )
        }
    }
}

image.png

快来动手试试吧!

相关文章
|
存储 iOS开发
SwiftUI极简教程17:Gestures手势的使用
SwiftUI极简教程17:Gestures手势的使用
990 0
SwiftUI极简教程17:Gestures手势的使用
|
程序员 索引
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
1050 0
SwiftUI极简教程18:SwipeCard卡片滑动效果的使用(上)
|
存储 索引
SwiftUI极简教程19:SwipeCard卡片滑动效果的使用(下)
SwiftUI极简教程19:SwipeCard卡片滑动效果的使用(下)
656 0
SwiftUI极简教程19:SwipeCard卡片滑动效果的使用(下)
|
Java Android开发
【安卓开发】Dialog对话框的学习和使用
【安卓开发】Dialog对话框的学习和使用
213 0
【安卓开发】Dialog对话框的学习和使用
|
API iOS开发
SwiftUI 中的自定义导航
默认情况下,SwiftUI提供的各种导航API在很大程度上是以用户直接输入为中心的——也就是说,导航是在系统响应例如按钮的点击和标签切换等事件时由系统本身处理的。
270 0
SwiftUI 中的自定义导航
SwiftUI极简教程28:TextEditor多行文本框的使用
SwiftUI极简教程28:TextEditor多行文本框的使用
1180 0
SwiftUI极简教程28:TextEditor多行文本框的使用
|
存储 索引
SwiftUI极简教程42:使用MatchedGeometryEffect构建一个导航菜单
在本章中,你将学会使用MatchedGeometryEffect构建一个导航菜单。 在构建SwiftUI应用过程中,我们常常会使用TabView构建底部菜单,但更多的时候会由于我们定制化的需求,需要我们自己绘制底部菜单。 那么本章中,我们就来试试构建一个底部导航菜单。
452 0
SwiftUI极简教程42:使用MatchedGeometryEffect构建一个导航菜单
|
存储
SwiftUI极简教程40:构建SearchBar搜索栏和TabView底部导航
在本章中,你将学会构建Search搜索进行列表搜索和TabView底部导航。 在上一章节中,我们完成了一个简单的ColourAtla色卡App,接下来我们继续完善App的相关内容。
750 0
SwiftUI极简教程40:构建SearchBar搜索栏和TabView底部导航
SwiftUI—借助sizeCategory预览不同字体下的文本视图
SwiftUI—借助sizeCategory预览不同字体下的文本视图
157 0
SwiftUI—借助sizeCategory预览不同字体下的文本视图
SwiftUI直通车系列(5)—— 自定义绘制
SwiftUI直通车系列(5)—— 自定义绘制
147 0
SwiftUI直通车系列(5)—— 自定义绘制