SwiftUI如何自定义支持View类型的导航标题并保留原生动画?
实现SwiftUI自定义View类型导航标题(保留原生特性)
核心方案:通过UIKit桥接复用原生导航栏特性
SwiftUI原生.navigationTitle仅支持字符串,但可以借助UIViewControllerRepresentable与UIKit互操作,利用UINavigationItem的titleView属性设置自定义视图,完全保留原生导航栏的滚动锚定、内联变形等动画,无需自行实现。
具体实现代码
1. 构建UIKit桥接容器
创建承载SwiftUI自定义视图的UIViewControllerRepresentable组件:
import SwiftUI struct CustomNavigationTitleHost<Content: View>: UIViewControllerRepresentable { let content: Content func makeUIViewController(context: Context) -> UIHostingController<Content> { let hostingController = UIHostingController(rootView: content) hostingController.view.backgroundColor = .clear hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] return hostingController } func updateUIViewController(_ uiViewController: UIHostingController<Content>, context: Context) { uiViewController.rootView = content } }
2. 扩展View添加自定义修饰符
给View扩展一个类似原生语法的修饰符,方便调用:
extension View { func customNavigationTitle<Content: View>(@ViewBuilder content: () -> Content) -> some View { self.background( CustomNavigationTitleHost(content: content()) .frame(height: 44) // 匹配原生导航栏标题高度 .accessibilityHidden(true) .onAppear { // 获取当前导航控制器并设置titleView guard let navController = UIApplication.shared.windows.first?.rootViewController as? UINavigationController else { return } navController.topViewController?.navigationItem.titleView = navController.topViewController?.view.subviews.first { $0 is UIHostingController<Content>.RootView }?.superview } ) } }
3. 使用示例
直接在NavigationStack/NavigationView内调用,传入任意SwiftUI视图作为标题:
struct DemoView: View { var body: some View { NavigationStack { ScrollView { ForEach(0..<50) { index in Text("列表项 \(index)") .padding() } } .customNavigationTitle { HStack(spacing: 8) { Image(systemName: "heart.fill") .foregroundColor(.red) Text("Fitness") .font(.title) .fontWeight(.bold) } } .navigationBarTitleDisplayMode(.inline) } } }
关键注意事项
- 必须在
NavigationStack(iOS 16+)或NavigationView(iOS 15及以下)内部使用该修饰符 - 自定义视图高度建议设为44pt,匹配原生导航栏标题默认高度,避免布局错乱
- 若需横竖屏适配,可在
CustomNavigationTitleHost的updateUIViewController方法中调整视图尺寸
开源库替代方案
不想自行实现桥接逻辑的话,可使用成熟开源库:
- SwiftUIX:提供增强版导航组件,支持自定义View类型标题,完全兼容原生动画
- NavigationStackEx:针对
NavigationStack扩展,使用方式与原生修饰符高度一致
内容的提问来源于stack exchange,提问作者Sheldon
相关产品推荐
相关产品推荐

