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

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
    }
}

代码说明

  1. 数字索引替换字符串索引:用selectedIndex(整数)替代原来的selectedIndexStr,更方便比较切换方向
  2. 后退判断逻辑:通过isBackwardTransition计算属性判断当前切换是否为后退(当前索引小于上一个索引)
  3. 动画设置:后退时,目标视图初始偏移到屏幕底部(offset(y: UIScreen.main.bounds.height))且完全透明,动画过程中移回原位并显示;前进时保持默认动画
  4. 按钮点击逻辑:点击按钮时先记录上一个索引,再更新当前索引,确保方向判断准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:56:08