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

SwiftUI中如何通过枚举实现视图跳转(替代叠加显示)

问题

刚接触SwiftUI,跟着教程做了包含5个视图(搜索、主页等)的TabBar导航,点击TabBar项能正常切换对应视图。但在HomeView页面中点击卡片按钮时,selectedSection对应的文本内容会叠加显示在HomeView之上,想实现完全打开新视图的效果。

解决方案

要实现完全跳转新视图的效果,需要用SwiftUI的**导航栈(NavigationStack)**管理视图层级,替代当前直接在ZStack中叠加视图的方式。具体步骤如下:

1. 给主视图添加导航栈

在ContentView中用NavigationStack包裹原有内容,让视图具备导航能力。

2. 配置导航目标

通过navigationDestination修饰符,关联selectedSection的枚举值与对应目标视图,当selectedSection变化时自动触发跳转。

3. 调整枚举协议

给Features枚举添加Hashable协议,确保导航栈能识别并响应状态变化。

修改后的代码

ContentView 修改后

struct ContentView: View {
    @AppStorage("selectedTab") var selectedTab: Tab = .home
    @AppStorage("selectedSection") var selectedSection: Features = .calculators
    
    @State var isOpen = false
    @State var show = false
    let button = RiveViewModel(fileName: "menu_button", stateMachineName: "State Machine", autoPlay: false)
    
    var body: some View {
        NavigationStack { // 添加导航栈
            ZStack {
                Color("Background 2").ignoresSafeArea()
                SideMenu()
                    .opacity(isOpen ? 1 : 0)
                    .offset(x: isOpen ? 0 : -300)
                    .rotation3DEffect(.degrees(isOpen ? 0 : 30), axis: (x: 0, y: 1, z: 0))
                
                Group {
                    switch selectedTab {
                    case .home:
                        HomeView()
                            // 绑定导航目标:根据selectedSection跳转对应视图
                            .navigationDestination(for: Features.self) { feature in
                                switch feature {
                                case .calculators:
                                    Text("Calculators")
                                        .navigationTitle("Calculators")
                                case .projects:
                                    Text("Projects")
                                        .navigationTitle("Projects")
                                case .kvFinder:
                                    Text("kv Finder")
                                        .navigationTitle("KV Finder")
                                }
                            }
                    case .search:
                        Text("Search")
                    case .star:
                        Text("Favorites")
                    case .bell:
                        Text("Bell")
                    case .user:
                        Text("User")
                    }
                }
            }
        }
    }
}

HomeView 保持原有逻辑

struct HomeView: View {
    @AppStorage("selectedSection") var selectedSection: Features = .calculators
    let sections: [Section] = [
        Section(title: "TAB Calculations", subtitle: "Find all basic and advanced HVAC calculations", caption: "3 sections - over 40 calculators", color: Color(hex: "7850F0"), image: Image(systemName: "x.squareroot"), features: .calculators),
        Section(title: "Upcoming Projects", subtitle: "Find upcoming and current commissioning projects.", caption: "Over 150 projects", color: Color(hex: "6792FF"), image: Image(systemName: "folder.fill.badge.plus"), features: .projects),
        Section(title: "Valve Kv Finder", subtitle: "Quickly determine valve flow rates from brands such as Oventropp, IMI TA and Danfoss", caption: "150 tables", color: Color(hex: "005FE7"), image: Image(systemName: "magnifyingglass"), features: .kvFinder)
    ]
    
    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            Text("Welcome")
                .customFont(.largeTitle)
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.horizontal, 20)
            
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 20) {
                    ForEach(sections) { section in
                        Button {
                            selectedSection = section.features // 保持原有赋值逻辑
                        } label : {
                            VCard(section: section)
                        }
                    }
                }
                .padding(.horizontal, 20)
            }
        }
    }
}

调整Features枚举

enum Features: String, Hashable { // 添加Hashable协议
    case calculators
    case projects
    case kvFinder
}

其他代码保持不变

struct Section: Identifiable {
    var id = UUID()
    var title: String
    var subtitle: String
    var caption: String
    var color: Color
    var image: Image
    var features: Features
}

// 示例VCard实现
struct VCard: View {
    let section: Section
    var body: some View {
        RoundedRectangle(cornerRadius: 16)
            .fill(section.color)
            .frame(width: 280, height: 180)
            .overlay(
                VStack(alignment: .leading, spacing: 8) {
                    section.image
                        .foregroundColor(.white)
                        .font(.title)
                    Text(section.title)
                        .foregroundColor(.white)
                        .font(.headline)
                    Text(section.subtitle)
                        .foregroundColor(.white.opacity(0.8))
                        .font(.caption)
                }
                .padding()
            )
    }
}

// 示例Tab枚举
enum Tab: String {
    case home, search, star, bell, user
}
关键说明
  • 导航栈会自动添加返回按钮,符合iOS原生导航交互逻辑,用户可从新视图返回HomeView。
  • 导航目标里的Text可替换为你自定义的完整视图(如CalculatorsView、ProjectsView),实现更复杂的页面内容。
  • 必须给Features添加Hashable协议,否则navigationDestination无法识别枚举类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:25:25