fullScreenCover
是什么?
#
fullScreenCover
是 SwiftUI 中的一种视图呈现方式,用于以 全屏覆盖的方式 显示一个模态视图(类似 Modal
的表现形式)。与 sheet
不同,fullScreenCover
会完全覆盖当前视图,而不会在屏幕底部滑出。
何时使用 fullScreenCover
?
#
fullScreenCover
通常用于需要 完全占据屏幕 的场景,例如:
- 创建引导页(Onboarding),用户需要完成某些操作后才能返回主界面。
- 显示登录页面(Login),强制用户登录完成后再返回原内容。
- 显示视频或照片预览(如全屏观看视频或图片)。
- 在游戏场景中使用全屏视图。
- 以全屏方式展示内容,并需要完全沉浸式体验。
fullScreenCover
的语法
#
.fullScreenCover(isPresented: $flag, content: {
FullScreenView()
})
isPresented
:绑定到一个布尔值,当true
时,显示全屏覆盖的内容;当false
时,关闭全屏内容。content
:一个 SwiftUI 视图,表示全屏覆盖的内容。
与 sheet
的区别
#
sheet
和 fullScreenCover
都用于模态显示内容,但两者有关键区别:
属性/表现 | sheet | fullScreenCover |
---|---|---|
覆盖级别 | 从屏幕底部滑出,覆盖部分屏幕。 | 全屏展示,完全覆盖屏幕视图。 |
关闭方式 | 默认可以通过下滑手势关闭(可禁用)。 | 没有下滑关闭,需明确触发返回操作。 |
使用场景 | 显示小型模态界面,如设置或表单。 | 强制需要全屏操作或沉浸式体验的场景。 |
示例代码 #
1. 基本用法 #
一个简单的例子,点击按钮时以全屏方式显示一段文本,点击“关闭”按钮返回主视图。
import SwiftUI
struct ContentView: View {
@State private var showFullScreen = false
var body: some View {
Button("Show FullScreenCover") {
showFullScreen = true
}
.fullScreenCover(isPresented: $showFullScreen) {
FullScreenView()
}
}
}
struct FullScreenView: View {
@Environment(\.dismiss) var dismiss // 用于手动关闭当前视图
var body: some View {
VStack {
Text("This is a Full Screen Cover!")
.font(.title)
.padding()
Button("Close") {
dismiss() // 手动关闭视图
}
.buttonStyle(.borderedProminent)
}
}
}
2. 登录页面(强制动作场景) #
在登录场景中,可以使用 fullScreenCover
强制用户完成登录后才能返回主界面。
import SwiftUI
struct ContentView: View {
@State private var isLoggedIn = false
@State private var showingLoginScreen = true
var body: some View {
Text("Welcome to the App!")
.font(.largeTitle)
.padding()
.fullScreenCover(isPresented: $showingLoginScreen) {
if !isLoggedIn {
LoginView(isLoggedIn: $isLoggedIn, showingLoginScreen: $showingLoginScreen)
}
}
}
}
struct LoginView: View {
@Binding var isLoggedIn: Bool // 登录状态
@Binding var showingLoginScreen: Bool
var body: some View {
VStack {
Text("Login")
.font(.title)
Button("Log In") {
isLoggedIn = true
showingLoginScreen = false // 关闭登录视图
}
.buttonStyle(.borderedProminent)
}
}
}
效果: #
- 应用启动时
fullScreenCover
默认显示登录界面。 - 用户登录后,返回主视图,不再显示登录页面。
3. 引导页(Onboarding) #
通过 fullScreenCover
强制用户完成引导流程后进入主界面。
import SwiftUI
struct ContentView: View {
@State private var showingOnboarding = true
var body: some View {
Text("Main App Content")
.font(.largeTitle)
.padding()
.fullScreenCover(isPresented: $showingOnboarding) {
OnboardingView(showingOnboarding: $showingOnboarding)
}
}
}
struct OnboardingView: View {
@Binding var showingOnboarding: Bool
var body: some View {
TabView {
VStack {
Text("Welcome to Onboarding 1")
Spacer()
}
VStack {
Text("Welcome to Onboarding 2")
Spacer()
}
VStack {
Text("Welcome to Onboarding 3")
Button("Get Started") {
showingOnboarding = false
}
.buttonStyle(.borderedProminent)
}
}
.tabViewStyle(PageTabViewStyle())
}
}
效果: #
- 应用启动时
fullScreenCover
显示引导页面。 - 用户完成引导后,返回主视图。
高级用法 #
1. 结合 ignoresSafeArea
实现沉浸式页面
#
如果需要实现真正的全屏(例如隐藏系统状态栏、顶部导航区域或底部 Home Indicator),可以结合 .ignoresSafeArea
修饰符。
import SwiftUI
struct FullScreenCoverExample: View {
@State private var showFullScreen = false
var body: some View {
Button("Show Immersive Full Screen") {
showFullScreen = true
}
.fullScreenCover(isPresented: $showFullScreen) {
ImmersiveView()
}
}
}
struct ImmersiveView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
ZStack {
Color.black // 黑色背景
.ignoresSafeArea() // 忽略安全区域
VStack {
Text("Immersive Fullscreen")
.foregroundColor(.white)
.font(.title)
Button("Close") {
dismiss()
}
.buttonStyle(.borderedProminent)
.foregroundColor(.white)
}
}
}
}
2. 禁用交互式关闭 #
在某些情况下,可能需要强制用户只能通过特定按钮返回,而无法通过边缘滑动手势关闭全屏视图。你可以结合 interactiveDismissDisabled(true)
方法实现。
.fullScreenCover(isPresented: $showingModal) {
YourFullScreenView()
.interactiveDismissDisabled(true) // 禁用滑动关闭
}
注意事项 #
生命周期: SwiftUI 的
fullScreenCover
会在显示或关闭时触发onAppear
和onDisappear
。isPresented
双向绑定: 确保isPresented
的状态在需要时能准确更新(如通过按钮关闭)。手势交互: 默认情况下,
fullScreenCover
不允许通过拖拽(下滑)关闭,但可以通过按钮或其他手动操作来关闭。层级显示:
fullScreenCover
会覆盖当前视图的所有内容,因此适合需要页面切换完全独立的场景。
总结 #
SwiftUI 的 fullScreenCover
是一种非常强大的工具,适用于需要全屏覆盖的模态视图展示场景。和 sheet
相比,它提供了更强的沉浸感和不被干扰的用户体验,同时可以通过灵活的状态绑定和修饰符(如 .interactiveDismissDisabled
、.ignoresSafeArea
)实现多样化的功能。