Layout — fullScreenCover

fullScreenCover 是什么? #

fullScreenCoverSwiftUI 中的一种视图呈现方式,用于以 全屏覆盖的方式 显示一个模态视图(类似 Modal 的表现形式)。与 sheet 不同,fullScreenCover 会完全覆盖当前视图,而不会在屏幕底部滑出。


何时使用 fullScreenCover #

fullScreenCover 通常用于需要 完全占据屏幕 的场景,例如:

  1. 创建引导页(Onboarding),用户需要完成某些操作后才能返回主界面。
  2. 显示登录页面(Login),强制用户登录完成后再返回原内容。
  3. 显示视频或照片预览(如全屏观看视频或图片)。
  4. 在游戏场景中使用全屏视图。
  5. 以全屏方式展示内容,并需要完全沉浸式体验。

fullScreenCover 的语法 #

.fullScreenCover(isPresented: $flag, content: {
    FullScreenView()
})
  • isPresented:绑定到一个布尔值,当 true 时,显示全屏覆盖的内容;当 false 时,关闭全屏内容。
  • content:一个 SwiftUI 视图,表示全屏覆盖的内容。

sheet 的区别 #

sheetfullScreenCover 都用于模态显示内容,但两者有关键区别:

属性/表现sheetfullScreenCover
覆盖级别从屏幕底部滑出,覆盖部分屏幕。全屏展示,完全覆盖屏幕视图。
关闭方式默认可以通过下滑手势关闭(可禁用)。没有下滑关闭,需明确触发返回操作。
使用场景显示小型模态界面,如设置或表单。强制需要全屏操作或沉浸式体验的场景。

示例代码 #

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

效果: #

  1. 应用启动时 fullScreenCover 默认显示登录界面。
  2. 用户登录后,返回主视图,不再显示登录页面。

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())
    }
}

效果: #

  1. 应用启动时 fullScreenCover 显示引导页面。
  2. 用户完成引导后,返回主视图。

高级用法 #

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) // 禁用滑动关闭
}

注意事项 #

  1. 生命周期: SwiftUI 的 fullScreenCover 会在显示或关闭时触发 onAppearonDisappear

  2. isPresented 双向绑定: 确保 isPresented 的状态在需要时能准确更新(如通过按钮关闭)。

  3. 手势交互: 默认情况下,fullScreenCover 不允许通过拖拽(下滑)关闭,但可以通过按钮或其他手动操作来关闭。

  4. 层级显示: fullScreenCover 会覆盖当前视图的所有内容,因此适合需要页面切换完全独立的场景。


总结 #

SwiftUI 的 fullScreenCover 是一种非常强大的工具,适用于需要全屏覆盖的模态视图展示场景。和 sheet 相比,它提供了更强的沉浸感和不被干扰的用户体验,同时可以通过灵活的状态绑定和修饰符(如 .interactiveDismissDisabled.ignoresSafeArea)实现多样化的功能。

本文共 1451 字,上次修改于 Jan 21, 2025