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: - 主视图 struct ContentView: View { // MARK: - 状态属性 @State private var showModal = false // 控制用户资料弹窗显示 @State private var showSettings = false // 控制设置页面显示 @State private var contentOffset: CGFloat = 0 // 内容偏移量 @State private var showLogin = false // MARK: - 主体视图 var body: some View { NavigationView { 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() // 登录按钮 NavigationLink(destination: LoginView()) { Text("登录") .font(.headline) .padding(.horizontal, 16) .padding(.vertical, 8) .background(Color.blue) .foregroundColor(.white) .cornerRadius(8) } .padding(.trailing) } 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.3) .edgesIgnoringSafeArea(.all) .onTapGesture(perform: hideSettings) .transition(.opacity) } if showSettings { SettingsView(isPresented: $showSettings) .transition(.move(edge: .leading)) .zIndex(1) } } .animation(.spring(response: 0.6, dampingFraction: 0.8), value: showSettings) } .navigationBarHidden(true) } } /// 显示用户资料弹窗 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 } } } // MARK: - 预览 #Preview { ContentView() }