SwiftUI如何替换或隐藏第三方视图中的ToolbarItem
替换/隐藏第三方SwiftUI视图自带ToolbarItem的解决方法
第三方SDK提供的ThirdPartyView自带了导航栏左侧的ToolbarItem,当我们在自定义视图MyView中为其添加同位置的ToolbarItem时,两个按钮会并存显示,无法直接替换或隐藏原有按钮。相关代码如下:
第三方视图代码:
struct ThirdPartyView: View { var body: some View { VStack { Text("Hi!") } .toolbar { ToolbarItem(placement: .navigationBarLeading) { Image(systemName: "arrow.left") } } } }
自定义视图代码:
struct MyView: View { var body: some View { ThirdPartyView() .toolbar { ToolbarItem(placement: .navigationBarLeading) { Image(systemName: "arrow.down") } } } }
导航栈结构:
struct DisplayedView: View { var body: some View { NavigationStack { MyView() } } }
方案一:通过UIKit API直接修改导航栏按钮(推荐保留系统导航栏样式时使用)
由于SwiftUI的Toolbar是累积式的,子视图和父视图的Toolbar会合并显示,因此可以借助UIKit的导航控制器API直接替换或清空原有按钮:
struct MyView: View { var body: some View { ThirdPartyView() .onAppear { guard let navVC = findTopNavigationController() else { return } // 替换为自定义按钮 let customButton = UIBarButtonItem( image: UIImage(systemName: "arrow.down"), style: .plain, target: nil, action: #selector(customButtonTapped) ) navVC.topViewController?.navigationItem.leftBarButtonItems = [customButton] } .onDisappear { // 页面消失时恢复原有状态(可选) guard let navVC = findTopNavigationController() else { return } navVC.topViewController?.navigationItem.leftBarButtonItems = nil } } @objc private func customButtonTapped() { // 自定义按钮的点击逻辑 } // 找到当前最顶层的导航控制器 private func findTopNavigationController() -> UINavigationController? { let keyWindow = UIApplication.shared.connectedScenes .filter { $0.activationState == .foregroundActive } .compactMap { $0 as? UIWindowScene } .first? .windows .first { $0.isKeyWindow } return keyWindow?.rootViewController?.topMost() as? UINavigationController } } // 扩展UIViewController,递归找到最顶层的视图控制器 extension UIViewController { func topMost() -> UIViewController { if let presented = presentedViewController { return presented.topMost() } if let nav = self as? UINavigationController { return nav.visibleViewController?.topMost() ?? nav } if let tab = self as? UITabBarController { return tab.selectedViewController?.topMost() ?? tab } return self } }
方案二:隐藏原有导航栏,自定义导航栏(适合完全自定义样式时使用)
直接隐藏第三方视图的导航栏,然后自行构建导航栏组件:
struct MyView: View { var body: some View { VStack(spacing: 0) { // 自定义导航栏 HStack { Image(systemName: "arrow.down") .onTapGesture { // 按钮点击逻辑 } Spacer() } .padding(.horizontal, 16) .padding(.vertical, 12) .background(Color(.systemBackground)) // 隐藏第三方视图的导航栏 ThirdPartyView() .toolbar(.hidden, for: .navigationBar) } } }
内容的提问来源于stack exchange,提问作者timbre timbre
相关产品推荐
相关产品推荐

