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

SwiftUI中如何实现导航标题显示模式的平滑切换动画?

SwiftUI中实现导航栏显示模式的平滑切换动画

直接通过withAnimation切换navigationBarTitle的displayMode时动画生硬,核心原因是SwiftUI原生对该状态的过渡动画支持不够完善,以下是两种可行的解决方案:

方案一:结合UIKit动画实现原生流畅过渡

利用UIKit成熟的导航栏动画系统,能完美复现系统自带的largeTitle与inline模式切换动画:

  1. 先实现一个获取当前导航控制器的辅助方法:
private func getCurrentNavigationController() -> UINavigationController? {
    guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
          let window = scene.windows.first,
          let rootViewController = window.rootViewController else {
        return nil
    }
    return rootViewController.children.first as? UINavigationController ?? rootViewController as? UINavigationController
}
  1. 修改视图代码,用UIKit的UIView.animate包裹状态切换:
struct ContentView: View {
    @State private var isLargeTitle = true

    var body: some View {
        NavigationView {
            VStack {
                Text("Hello, SwiftUI!")
                    .navigationBarTitle("Title")
                    .navigationBarTitleDisplayMode(isLargeTitle ? .large : .inline)
                
                Button("Toggle Display Mode") {
                    UIView.animate(withDuration: 0.3, options: .curveEaseInOut) {
                        isLargeTitle.toggle()
                        getCurrentNavigationController()?.navigationBar.sizeToFit()
                    }
                }
            }
        }
    }
}

这种方法保留了系统largeTitle的所有特性(比如滚动时自动收缩),动画效果和原生切换完全一致。

方案二:纯SwiftUI自定义标题动画

如果不想依赖UIKit,可以自定义标题视图,完全控制动画过程:

struct ContentView: View {
    @State private var isLargeTitle = true

    var body: some View {
        NavigationView {
            VStack {
                Text("Hello, SwiftUI!")
                
                Button("Toggle Display Mode") {
                    withAnimation(.easeInOut(duration: 0.3)) {
                        isLargeTitle.toggle()
                    }
                }
            }
            .toolbar {
                ToolbarItem(placement: .principal) {
                    Text("Title")
                        .font(isLargeTitle ? .largeTitle.weight(.bold) : .headline)
                        .transition(.scale.combined(with: .opacity))
                }
            }
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

这种方法的优点是纯SwiftUI实现,动画流畅度高,但会失去系统largeTitle的滚动自动收缩特性,适合不需要该特性的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:06:16