SwiftUI 提供了多种导航方式,让我为你详细介绍主要的导航模式和相关组件。
1. NavigationStack (iOS 16+)
基本用法
swift
struct ContentView: View {
var body: some View {
NavigationStack {
List {
NavigationLink("前往详情页", value: "详情内容")
NavigationLink("设置", value: "设置页面")
}
.navigationDestination(for: String.self) { value in
DetailView(content: value)
}
}
}
}
struct DetailView: View {
let content: String
var body: some View {
Text("详情: \(content)")
.navigationTitle("详情页")
}
}
多类型导航
swift
enum Route: Hashable {
case product(Int)
case category(String)
case settings
}
struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
NavigationLink("产品123", value: Route.product(123))
NavigationLink("电子产品", value: Route.category("electronics"))
NavigationLink("设置", value: Route.settings)
}
.navigationDestination(for: Route.self) { route in
switch route {
case .product(let id):
ProductView(productId: id)
case .category(let name):
CategoryView(category: name)
case .settings:
SettingsView()
}
}
}
}
}
2. NavigationView (iOS 13-16)
swift
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: DetailView()) {
Label("详情页面", systemImage: "star")
}
NavigationLink(destination: SettingsView()) {
Label("设置", systemImage: "gear")
}
}
.navigationTitle("主页面")
}
}
}
3. 编程式导航
使用 NavigationPath
swift
struct ContentView: View {
@State private var navigationPath = NavigationPath()
var body: some View {
NavigationStack(path: $navigationPath) {
VStack(spacing: 20) {
Button("跳转到产品页") {
navigationPath.append(Route.product(456))
}
Button("跳转到分类页") {
navigationPath.append(Route.category("books"))
}
Button("多层级跳转") {
navigationPath.append(Route.category("electronics"))
navigationPath.append(Route.product(789))
}
Button("返回根页面") {
navigationPath.removeLast(navigationPath.count)
}
Button("上一步") {
guard !navigationPath.isEmpty else { return }
navigationPath.removeLast()
}
}
.navigationDestination(for: Route.self) { route in
// 路由处理...
}
}
}
}
4. Sheet 和 FullScreenCover
模态展示
swift
struct ContentView: View {
@State private var showingSheet = false
@State private var showingFullScreen = false
var body: some View {
VStack(spacing: 20) {
Button("显示 Sheet") {
showingSheet = true
}
Button("全屏显示") {
showingFullScreen = true
}
}
.sheet(isPresented: $showingSheet) {
SheetView()
}
.fullScreenCover(isPresented: $showingFullScreen) {
FullScreenView()
}
}
}
struct SheetView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationView {
Text("这是 Sheet 视图")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("完成") {
dismiss()
}
}
}
}
}
}
5. TabView 标签导航
swift
struct MainTabView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Label("首页", systemImage: "house")
}
SearchView()
.tabItem {
Label("搜索", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("我的", systemImage: "person")
}
}
}
}
6. 复杂导航示例
带导航栏的完整示例
swift
struct MainView: View {
@State private var navigationPath = NavigationPath()
var body: some View {
NavigationStack(path: $navigationPath) {
ProductListView()
.navigationTitle("产品列表")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("设置") {
navigationPath.append(AppRoute.settings)
}
}
}
.navigationDestination(for: AppRoute.self) { route in
route.destination
}
}
}
}
enum AppRoute: Hashable {
case productDetail(Product)
case category(String)
case settings
case profile
@ViewBuilder
var destination: some View {
switch self {
case .productDetail(let product):
ProductDetailView(product: product)
case .category(let category):
CategoryView(category: category)
case .settings:
SettingsView()
case .profile:
ProfileView()
}
}
}
自定义导航栏
swift
struct CustomNavigationView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationView {
Text("自定义导航栏")
.navigationTitle("标题")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
// 左侧按钮
ToolbarItem(placement: .navigationBarLeading) {
Button("取消") {
dismiss()
}
}
// 右侧按钮
ToolbarItem(placement: .navigationBarTrailing) {
Button("保存") {
// 保存操作
}
.bold()
}
}
}
}
}
7. 导航状态管理
swift
class NavigationManager: ObservableObject {
@Published var path = NavigationPath()
func navigateToProduct(_ id: Int) {
path.append(Route.product(id))
}
func navigateToCategory(_ name: String) {
path.append(Route.category(name))
}
func popToRoot() {
path.removeLast(path.count)
}
}
struct AppView: View {
@StateObject private var navManager = NavigationManager()
var body: some View {
NavigationStack(path: $navManager.path) {
ContentView()
.navigationDestination(for: Route.self) { route in
// 路由处理
}
}
.environmentObject(navManager)
}
}
主要特点总结
- NavigationStack: iOS 16+ 推荐使用,支持类型安全的路由
- 编程式导航: 通过状态管理控制导航流程
- 模态展示: Sheet 和 FullScreenCover 用于临时内容
- 标签导航: TabView 用于主要功能模块切换
- 灵活的路由系统: 支持复杂导航逻辑和深度链接
这些导航方式可以组合使用,创建出符合你应用需求的完整导航体验。