import SwiftUI // MARK: - 自定义过渡动画 extension AnyTransition { /// 创建从左向右的滑动过渡动画 static var slideFromLeading: AnyTransition { .asymmetric( insertion: .move(edge: .trailing).combined(with: .opacity), // 从右侧滑入 removal: .move(edge: .leading).combined(with: .opacity) // 向左侧滑出 ) } } // MARK: - 路由定义 enum Route: Hashable { case settings // 设置页面路由 } // MARK: - 主视图 struct ContentView: View { // MARK: - 状态属性 @State private var showModal = false // 控制用户资料弹窗显示 @State private var showSettings = false // 控制设置页面显示 @State private var navigationPath = NavigationPath() // 导航路径 @State private var contentOffset: CGFloat = 0 // 内容偏移量 // MARK: - 主体视图 var body: some View { NavigationStack(path: $navigationPath) { // 调试信息 let _ = Self._printChanges() let _ = print("导航路径已更新: \(navigationPath)") // 主内容区域 ZStack { // 主内容视图 VStack { VStack(spacing: 20) { // 状态栏占位 Spacer().frame(height: UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) // 顶部导航栏 - 左侧设置按钮 HStack { // 设置按钮 Button(action: showUserProfile) { Image(systemName: "gearshape") .font(.title2) .padding() } Spacer() // 将按钮推到左侧 } Spacer() // 内容列表 List { Section(header: Text("我的收藏")) { ForEach(1...5, id: \.self) { item in HStack { Image(systemName: "photo") .foregroundColor(.blue) .frame(width: 40, height: 40) .background(Color.blue.opacity(0.1)) .cornerRadius(8) VStack(alignment: .leading, spacing: 4) { Text("项目 \(item)") .font(.headline) Text("这是第\(item)个项目的描述") .font(.subheadline) .foregroundColor(.secondary) } Spacer() Image(systemName: "chevron.right") .foregroundColor(.gray) } .padding(.vertical, 4) } } Section(header: Text("最近活动")) { ForEach(6...10, id: \.self) { item in HStack { Image(systemName: "clock") .foregroundColor(.orange) .frame(width: 40, height: 40) .background(Color.orange.opacity(0.1)) .cornerRadius(8) VStack(alignment: .leading, spacing: 4) { Text("活动 \(item)") .font(.headline) Text("\(item)分钟前更新") .font(.subheadline) .foregroundColor(.secondary) } Spacer() Text("查看") .font(.caption) .padding(6) .background(Color.blue.opacity(0.1)) .foregroundColor(.blue) .cornerRadius(4) } .padding(.vertical, 4) } } } .listStyle(GroupedListStyle()) .padding(.top, 0) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(.systemBackground)) // 当显示弹窗时,主内容向右偏移 .offset(x: showModal ? UIScreen.main.bounds.width * 0.8 : 0) // 页面内元素的动画 .animation(.spring(response: 0.6, dampingFraction: 0.8), value: showModal) .edgesIgnoringSafeArea(.all) } // 用户资料弹窗 SlideInModal( isPresented: $showModal, onDismiss: hideUserProfile ) { UserProfileModal( showModal: $showModal, showSettings: $showSettings ) } // 当显示设置页面时,将弹窗向右移出屏幕 .offset(x: showSettings ? UIScreen.main.bounds.width : 0) .animation(.spring(response: 0.6, dampingFraction: 0.8), value: showSettings) // 设置页面遮罩层 ZStack { // 半透明遮罩 if showSettings { Color.black.opacity(0) .edgesIgnoringSafeArea(.all) .onTapGesture(perform: hideSettings) .transition(.opacity) } // 设置页面 if showSettings { SettingsView(isPresented: $showSettings) .transition(.move(edge: .leading)) // 从左侧滑入 .zIndex(1) // 确保设置页面在其他内容之上 .onAppear(perform: resetNavigationPath) } } .animation(.spring(response: 0.6, dampingFraction: 0.8), value: showSettings) } } } // MARK: - 私有方法 /// 显示用户资料弹窗 private func showUserProfile() { withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) { showModal.toggle() } } /// 隐藏用户资料弹窗 private func hideUserProfile() { withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) { showModal = false } } /// 隐藏设置页面 private func hideSettings() { withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) { showSettings = false } } /// 重置导航路径 private func resetNavigationPath() { navigationPath.removeLast(navigationPath.count) } } // MARK: - 预览 #Preview { ContentView() }