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

Swift中Toast视图从导航栏下方滑入的动画实现问题

解决方案

问题出在默认的.move(edge: .top)动画是从屏幕**最顶部(导航栏上方的屏幕外区域)**滑入,所以会穿过导航栏。要实现从导航栏后方滑入的效果,需要调整动画的起始位置,让Toast从导航栏所在的位置开始向下滑到目标区域。

步骤1:获取导航栏高度

首先需要获取导航栏的总高度(包含顶部安全区域),可以用GeometryReader在SwiftUI中实现:

@State private var showToast = false
@State private var navigationBarHeight: CGFloat = 0

步骤2:调整Toast的位置与动画

通过offset固定Toast的最终位置在导航栏下方,同时自定义transition让动画从导航栏位置开始:

NavigationView {
    GeometryReader { geo in
        // 你的主内容视图
        Button("显示Toast") {
            withAnimation(.easeInOut(duration: 0.3)) {
                showToast = true
            }
            // 2秒后自动隐藏
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                withAnimation(.easeInOut(duration: 0.3)) {
                    showToast = false
                }
            }
        }
        .onAppear {
            // 获取顶部安全区域高度(包含导航栏)
            navigationBarHeight = geo.safeAreaInsets.top
        }
        .navigationTitle("测试页面")
    }
    .overlay(
        Group {
            if showToast {
                ToastView()
                    // 固定Toast在导航栏下方
                    .offset(y: navigationBarHeight)
                    // 自定义动画:从导航栏位置(向上偏移导航栏高度)滑入
                    .transition(.offset(y: -navigationBarHeight))
            }
        },
        alignment: .top
    )
}

原理说明

  • .offset(y: navigationBarHeight):让Toast的最终位置固定在导航栏下方,和你无动画时的正常位置一致。
  • .transition(.offset(y: -navigationBarHeight)):设置Toast出现时的起始位置为导航栏所在的区域(相对于最终位置向上偏移导航栏高度),因为导航栏的层级高于Toast,动画时Toast会被导航栏挡住上半部分,视觉上就像是从导航栏后方滑入。

备选方案(用UIKit获取精确高度)

如果safeAreaInsets.top不符合你的需求(比如自定义导航栏高度),可以通过UIKit直接获取导航栏高度:

.onAppear {
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
          let navController = windowScene.windows.first?.rootViewController as? UINavigationController else {
        return
    }
    // 导航栏自身高度 + 顶部安全区域高度
    navigationBarHeight = navController.navigationBar.frame.height + (windowScene.windows.first?.safeAreaInsets.top ?? 0)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 19:34:52