iOS开发 SwitftUI 13:提示、弹窗、上下文菜单

移动端没有桌面的窗口机制,各种弹窗都是系统功能。

目录

[.sheet 弹窗](#.sheet 弹窗)

[.fullScreenCover 全屏弹窗](#.fullScreenCover 全屏弹窗)

[.actionSheet 选项弹窗](#.actionSheet 选项弹窗)

[.alert 告警](#.alert 告警)

[.contextMenu 上下文菜单](#.contextMenu 上下文菜单)

汇总代码


.sheet 弹窗

sheet是一种弹窗机制,目前的默认实现是从屏幕下端升起,覆盖屏幕的绝大部分。

sheet属于整个屏幕,虽然把.sheet代码放在最外层符合逻辑,但实际上放在哪一层都没有关系,效果都是一样的。

基本的sheet用法:

Swift 复制代码
    @State var b = false
    @State var str = "info"

    var body: some View {
        Form {
            Button {b = true}label: {
                Text("打开sheet")
            }

            Text(str)
        }
        .sheet(isPresented: $b) {
            Text("关闭")
                .onTapGesture {
                    str = str + "+1"
                    b = false
                }
        }
    }

sheet需要一个变量来指示是否显示,需要关闭的时候设置变量为false即可。很明显,sheet是当前页面的一部分,只是根据指示显示出来。

初始:

点一下"打开sheet":

sheet打开,占据屏幕绝大部分。再点一下"关闭":

"info"变成了"info+1",符合预期。

由于界面和数据完全通过绑定变量交互,不用太关心sheet对象再次打开时是重新创建还是显示原来的对象,不像桌面程序,要考虑对象的创建和显示/隐藏。

.fullScreenCover 全屏弹窗

只需要简单地把.sheet替换成.FullScreenCover即可,效果:

除了全屏化没别的区别。

.actionSheet 选项弹窗

注意,已经被标记为过时,推荐用confirmationDialog代替。

ActionSheet提供类似菜单的操作,显示方式和前面的两种一样,用一个变量来表示是否显示,选项弹窗的关键代码如下:

Swift 复制代码
        .actionSheet(isPresented: $b) {
            return ActionSheet(
                title: Text("操作"),
                message: Text("随便选一个"),
                buttons: [
                    .cancel(
                        Text("取消"),
                        action: { str = str + "+cancel" }),
                    .destructive(
                        Text("危险 动作1"),
                        action: { str = str + "+destructive" }
                    ),
                    .default(
                        Text("默认 动作2"),
                        action: { str = str + "+default" }
                    ),
                ]
            )
        }

效果:

上面的代码在处理动作的时候并没有重置绑定变量b,设置的取消按钮也没有显示,但其实只需要点击弹窗以外的区域弹窗就会关闭,而且,任何一个动作结束都会自动重置绑定变量。

点击空白处取消:

再弹出来一次,点击一个选项:

动作都是正确执行的。

我们创建按钮的时候用了.destructive和.default,这两个是按钮的"角色",前一个表示是破坏性的,所以系统自动使用红色显示,后一个是默认,系统使用黑色显示。

.alert 告警

写法跟actionSheet差不多:

Swift 复制代码
        .alert(isPresented: $bAlert) {
            return Alert(title: Text("告警")
                         ,message: Text("确定吗?")
                         ,primaryButton: .destructive(Text("确认")){str = str + "+ok"}
                         ,secondaryButton: .default(Text("取消")){str = str + "+canecl"}
                         )
        }

效果:

说实话这东西真没有太多自定义的必要,但是从交互设计角度来说,文字应该居中显示。

.contextMenu 上下文菜单

上下文菜单需要通过长按呼出。跟前面的几个不同,不需要变量来指示是否显示,而且显示位置和修饰的对象有关。

下面的代码分别给整体和一个单独的Text设置了上下文菜单:

Swift 复制代码
    var body: some View {
        Form {
            //。。。。。。

            Text(str)
                .contextMenu {
                    Button("上下文菜单3") {
                        str = str + "+contextMenu3"
                    }
                    Button("上下文菜单4") {
                        str = str + "+contextMenu4"
                    }
                }
        }
        //。。。。。。
        .contextMenu {
            Button("上下文菜单1") {
                str = str + "+contextMenu1"
            }
            Button("上下文菜单2") {
                str = str + "+contextMenu2"
            }
        }
    }

长按Text的效果:

长按其余部分的效果:

汇总代码

本文的完整代码:

Swift 复制代码
import SwiftUI

struct SwiftUIViewPopup: View {
    @State var bSheet = false
    @State var bFullScreenCover = false
    @State var bActionSheet = false
    @State var bAlert = false
    @State var str = "info"

    var body: some View {
        Form {
            Button {
                bSheet = true
            } label: {
                Text("打开sheet")
            }
            Button {
                bFullScreenCover = true
            } label: {
                Text("打开FullScreenCover")
            }
            Button {
                bActionSheet = true
            } label: {
                Text("打开ActionSheet")
            }
            Button {
                bAlert = true
            } label: {
                Text("打开Alert")
            }

            Text(str)
                .contextMenu {
                    Button("上下文菜单3") {
                        str = str + "+contextMenu3"
                    }
                    Button("上下文菜单4") {
                        str = str + "+contextMenu4"
                    }
                }
        }
        .sheet(isPresented: $bSheet) {
            Text("关闭")
                .onTapGesture {
                    str = str + "+1"
                    bSheet = false
                }
        }
        .fullScreenCover(isPresented: $bFullScreenCover) {
            Text("关闭")
                .onTapGesture {
                    str = str + "+a"
                    bFullScreenCover = false
                }
        }
        .actionSheet(isPresented: $bActionSheet) {
            return ActionSheet(
                title: Text("操作"),
                message: Text("随便选一个"),
                buttons: [
                    .cancel(
                        Text("取消"),
                        action: { str = str + "+cancel" }
                    ),
                    .destructive(
                        Text("危险 动作1"),
                        action: { str = str + "+destructive" }
                    ),
                    .default(
                        Text("默认 动作2"),
                        action: { str = str + "+default" }
                    ),
                ]
            )
        }
        .alert(isPresented: $bAlert) {
            return Alert(
                title: Text("告警"),
                message: Text("确定吗?"),
                primaryButton: .destructive(Text("确认")) { str = str + "+ok" },
                secondaryButton: .default(Text("取消")) { str = str + "+canecl" }
            )
        }
        .contextMenu {
            Button("上下文菜单1") {
                str = str + "+contextMenu1"
            }
            Button("上下文菜单2") {
                str = str + "+contextMenu2"
            }
        }
    }
}

#Preview {
    SwiftUIViewPopup()
}
相关推荐
Anhty12 小时前
2026最新免费手机音频处理工具 !!
android·功能测试·ios·智能手机·音视频
2501_9159090614 小时前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
初雪云15 小时前
UniApp 云打包拿到 IPA 后,真正的发布工作才刚开始
ios·自动化·编辑器·产品经理·iphone
Lancker17 小时前
没有 Mac 也能上架 iOS:GitHub Actions 全自动构建 + 签名 + TestFlight 送审实录
macos·ios·github
茶底世界之下17 小时前
晚霞要多暖?用 Awaking 只改色温做一次取舍
ios
酒神dnspup19 小时前
多地区网站可用性监控怎么做?DNSPup 从基线到告警的完整实战
运维·ios·云计算·iphone·dns·网络监控
福兮说1 天前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
茶底世界之下2 天前
时间线效果层,为什么不能只复用一个处理器?
ios·swift
ZZH_AI项目交付2 天前
实时字幕负责快,本地录音负责不丢:一个 iOS 录音功能为什么需要两条链路
ios·ai编程
Cc.Y2 天前
Swift深度链接的极简之道
ios·cocoa·swift