SwiftUI 2下Mac Catalyst实现Big Sur风格透明侧边栏的配置问题
适配新SwiftUI生命周期的Big Sur透明侧边栏实现方案
你之前设置透明效果不生效的核心原因:
- Mac Catalyst下的双栏导航侧边栏,是由底层
UISplitViewController托管的系统级容器,自带固定的材料背景,在SwiftUI层级给侧边栏子视图设置.background(Color.clear),无法修改容器本身的背景优先级 - 网络上的旧配置方案基于手动持有AppDelegate/SceneDelegate的旧项目结构,但新SwiftUI App生命周期不需要手动创建委托对象,完全可以通过内嵌
UIViewControllerRepresentable的方式直接获取底层UIKit控制器完成配置,不需要改动项目的入口结构。
具体实现步骤
- 先创建无委托依赖的底层控制器修改逻辑
直接在项目中加入以下代码,不需要单独创建AppDelegate或SceneDelegate文件:import SwiftUI import UIKit // 平台判断,仅在Mac Catalyst环境下启用配置 #if targetEnvironment(macCatalyst) // 读取当前层级UISplitViewController的辅助视图 private struct SplitViewControllerReader: UIViewControllerRepresentable { let onFound: (UISplitViewController) -> Void func makeUIViewController(context: Context) -> UIViewController { let placeholderVC = UIViewController() DispatchQueue.main.async { // 向上遍历视图层级找到对应的SplitViewController var currentVC = placeholderVC.parent while let vc = currentVC { if let splitVC = vc as? UISplitViewController { onFound(splitVC) break } currentVC = vc.parent } } return placeholderVC } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} } // 透明侧边栏配置的ViewModifier private struct TransparentSidebarModifier: ViewModifier { func body(content: Content) -> some View { content.background( SplitViewControllerReader { splitVC in // 关闭侧边栏容器的不透明属性 splitVC.primaryColumnViewController?.view.isOpaque = false splitVC.primaryColumnViewController?.view.backgroundColor = .clear // 启用系统Big Sur风格的侧边栏材料效果 splitVC.primaryBackgroundStyle = .sidebar } ) } } extension View { /// 启用Mac Catalyst下Big Sur风格的透明侧边栏 func macCatalystTransparentSidebar() -> some View { self.modifier(TransparentSidebarModifier()) } } #endif - 修改你现有的项目入口代码
去掉之前给侧边栏视图单独加的无效.background(Color.clear)配置,直接在NavigationView上调用上面封装好的方法:@main struct SpenTApp: App { var body: some Scene { WindowGroup { NavigationView { SideBarView() DetailView() } .navigationViewStyle(DoubleColumnNavigationViewStyle()) #if targetEnvironment(macCatalyst) .macCatalystTransparentSidebar() #endif } } }
常见踩坑修正
- 如果你的侧边栏是用
List实现的,需要额外隐藏List自带的默认不透明背景,才能让透明效果正常生效:// 在SideBarView内部的List上添加配置 List { // 侧边栏菜单条目 } .listStyle(SidebarListStyle()) .scrollContentBackground(.hidden) // iOS 16+支持的API,用于隐藏List默认背景 - 不要强行把侧边栏设置为完全无材质的全透明,Big Sur风格的侧边栏是基于窗口统一的毛玻璃材料实现的,保持系统默认的窗口材料,仅移除侧边栏额外叠加的不透明背景,就能匹配系统原生视觉效果
- 所有配置逻辑都用平台判断做隔离,避免把Mac Catalyst的侧边栏配置套用到iOS端,导致iOS下的双栏导航出现背景穿透的显示bug
内容的提问来源于stack exchange,提问作者Tema Sysoev
相关产品推荐
相关产品推荐

