SwiftUI中点击按钮切换视图时添加指定返回导航动画的实现
实现返回视图时的从下到上切换动画
要实现返回(Feed→Attendance、Attendance→Dashboard)时的从下到上滑入动画,核心是区分视图切换的方向(前进/后退),并给不同方向设置对应的动画效果。以下是具体修改方案:
关键修改点
- 把字符串类型的选中索引改成数字索引,方便判断切换方向
- 新增状态变量记录上一个选中的索引
- 根据切换方向,给目标视图设置不同的初始偏移量,配合动画实现从下到上的效果
修改后的完整代码
struct DashboardBottomView: View { @StateObject var viewModel: AppDashboardViewModel @State var selectedClassInd: Int = 0 @State private var stringArray = ["Dashboard", "Attendance", "Feed"] @State private var selectedIndex: Int = 0 // 改用数字索引,默认选中第一个 @State private var previousIndex: Int = 0 // 记录上一个选中的索引,用于判断方向 private func viewForSelectedIndex() -> some View { switch stringArray[selectedIndex] { case "Dashboard": return AnyView(DashboardView(viewModel: viewModel)) case "Attendance": return AnyView(AttendanceSwipeView(viewModel: viewModel)) case "Feed": return AnyView(DashboardFeedView()) default: return AnyView(Text("Default View")) } } var body: some View { VStack(spacing: 0) { Spacer() ZStack { // 根据切换方向设置动画 viewForSelectedIndex() .toolbar(.hidden, for: .navigationBar) .offset(y: isBackwardTransition ? UIScreen.main.bounds.height : 0) .opacity(isBackwardTransition ? 0 : 1) .animation( isBackwardTransition ? .easeOut(duration: 0.3) : .default, value: selectedIndex ) } ZStack{ Color.appGreen2 ScrollView(.horizontal, showsIndicators: false) { LazyHGrid(rows: [GridItem(.flexible(), spacing: 0)], spacing: 0) { ForEach(stringArray.indices, id: \.self) { index in Button { // 先记录上一个索引,再更新当前索引 previousIndex = selectedIndex withAnimation { selectedIndex = index } } label: { VStack { Text(stringArray[index]) .font(.calibriBold(with: 14)) .foregroundColor(Color.white) .padding(.horizontal, 8) if selectedIndex == index { gradientDivider .frame(height: 2) } } .frame(height: 40) .frame(minWidth: 108) } .buttonStyle(.plain) } } .padding(.bottom, 0) .background(Color.appGreen2) } .frame(height: 55) } } .ignoresSafeArea() .onAppear { viewModel.fetchDashboardData { status in if status { stringArray = viewModel.dashboardButtonsArray selectedIndex = 0 previousIndex = 0 } } } } // 判断是否是后退切换:当前索引 < 上一个索引 private var isBackwardTransition: Bool { selectedIndex < previousIndex } }
代码说明
- 数字索引替换字符串索引:用
selectedIndex(整数)替代原来的selectedIndexStr,更方便比较切换方向 - 后退判断逻辑:通过
isBackwardTransition计算属性判断当前切换是否为后退(当前索引小于上一个索引) - 动画设置:后退时,目标视图初始偏移到屏幕底部(
offset(y: UIScreen.main.bounds.height))且完全透明,动画过程中移回原位并显示;前进时保持默认动画 - 按钮点击逻辑:点击按钮时先记录上一个索引,再更新当前索引,确保方向判断准确
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

