You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:从带导航返回按钮的视图跳转至全屏视图的问题

解决游戏菜单导航栏与全屏问题

问题背景

我正在使用NavigationView和NavigationLink制作游戏菜单,包含以下三个视图:

struct MainMenuView: View {
    var body: some View {
        NavigationView {
            // 相关内容
            NavigationLink(destination: CustomGameSettingsView()) {
                Text("Custom Game")
            }
        }
    }
}

CustomGameSettingsView

struct CustomGameSettingsView: View {
    var body: some View {
        NavigationView {
            // 用于修改游戏设置的UI
            NavigationLink(destination: MyGameView(customSettings)) {
                Text("Play Game!")
            }
        }
    }
}

注:CustomGameSettingsView会显示navigationBarBackButton

MyGameView

struct MyGameView: View {
    var body: some View {
        myGameViews {
            // 内容
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarHidden(true)
        .navigationBarTitle(Text("myGame"))
        .edgesIgnoringSafeArea([.top, .bottom])

        // 以上是我尝试移除返回按钮的操作
    }
    .onAppear() {
        self.navigationBarBackButtonHidden(true)
    } // 另一个尝试的方法
}

从MainMenuView跳转到CustomGameSettingsView后会出现navigationBarBackButton,进入MyGameView时该按钮仍存在。我希望设置页保留返回按钮,游戏页实现全屏,请问如何解决该问题?NavigationView是否并非合适的工具?


解决方案

核心问题分析

你当前的问题根源是在CustomGameSettingsView中重复嵌套了NavigationView,这会导致多个导航栈叠加,单独设置某一层的导航栏隐藏无法彻底移除返回按钮。NavigationView本身完全适合这类层级导航场景,只要正确使用即可。

具体修正步骤

  1. 移除子视图中的NavigationView:仅在根视图MainMenuView中保留一个NavigationView,所有子视图通过NavigationLink跳转,共享同一个导航栈。
  2. 正确设置游戏页的全屏属性:将导航栏隐藏和安全区域忽略属性直接应用到游戏视图的根容器上。

修正后的代码

MainMenuView(无需修改)

struct MainMenuView: View {
    var body: some View {
        NavigationView {
            // 其他菜单内容
            NavigationLink(destination: CustomGameSettingsView()) {
                Text("自定义游戏")
            }
        }
    }
}

CustomGameSettingsView(移除嵌套的NavigationView)

struct CustomGameSettingsView: View {
    // 示例:自定义设置属性,根据实际需求定义
    let customSettings = GameSettings()

    var body: some View {
        VStack {
            // 游戏设置UI内容
            Text("调整游戏设置")
            // 其他设置控件...

            NavigationLink(destination: MyGameView(customSettings: customSettings)) {
                Text("开始游戏!")
            }
        }
        .navigationTitle("自定义设置") // 在子视图中直接设置导航标题
    }
}

// 示例设置结构体
struct GameSettings {
    // 比如难度、关卡等自定义属性
}

MyGameView(修正全屏与导航栏隐藏)

struct MyGameView: View {
    let customSettings: GameSettings

    var body: some View {
        // 游戏视图根容器(比如ZStack/VStack)
        ZStack {
            // 你的游戏内容
            Color.black.edgesIgnoringSafeArea(.all)
            Text("游戏界面")
                .foregroundColor(.white)
        }
        .navigationBarBackButtonHidden(true) // 隐藏返回按钮
        .navigationBarHidden(true) // 隐藏整个导航栏
        .edgesIgnoringSafeArea([.top, .bottom]) // 忽略安全区域实现全屏
    }
}

额外优化(iOS 16+)

如果你的项目支持iOS 16及以上版本,推荐使用NavigationStack替代NavigationView,它的导航栈管理更直观,API更简洁:

struct MainMenuView: View {
    var body: some View {
        NavigationStack {
            // 其他菜单内容
            NavigationLink("自定义游戏", destination: CustomGameSettingsView())
        }
    }
}

游戏页返回逻辑

如果需要从游戏页手动返回菜单,可以在游戏内添加自定义按钮,通过@Environment(\.presentationMode)实现返回:

struct MyGameView: View {
    let customSettings: GameSettings
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        ZStack {
            // 游戏内容...
            
            // 自定义返回按钮(比如放在角落)
            Button("返回菜单") {
                presentationMode.wrappedValue.dismiss()
            }
            .foregroundColor(.white)
            .position(x: 50, y: 50)
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarHidden(true)
        .edgesIgnoringSafeArea([.top, .bottom])
    }
}

内容的提问来源于stack exchange,提问作者Randy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 21:36:21