SwiftUI macOS下TabView嵌套NavigationSplitView侧边栏按钮重复问题求助
问题描述
在macOS 13.2(Xcode 14.2)系统中,使用SwiftUI创建包含4个TabItem的TabView,每个TabItem对应一个独立的NavigationSplitView时,会出现侧边栏按钮重复显示的问题,但该问题在iPad上不存在。需要修复为仅显示当前选中标签页对应的NavigationSplitView的侧边栏按钮。
代码示例
struct ContentView: View { var body: some View { TabView() { Tab1View().tabItem { Label("Tab1", systemImage: "star")} Tab2View().tabItem { Label("Tab2", systemImage: "star")} Tab3View().tabItem { Label("Tab3", systemImage: "star")} Tab4View().tabItem { Label("Tab4", systemImage: "star")} } } } struct Tab1View: View { var body: some View { NavigationSplitView { Text("Tab1") }detail: { Text("Detail Tab1") } .navigationSplitViewStyle(.automatic) } } // Tab2View, Tab3View, Tab4View与Tab1View类似
解决方案
方法一:通过选中状态控制非活跃标签的侧边栏按钮
这种方法通过绑定TabView的选中状态,让非当前选中的标签页隐藏侧边栏按钮,仅保留活跃标签的按钮。
- 更新主视图,添加选中状态并绑定到TabView:
struct ContentView: View { @State private var selectedTab = 0 var body: some View { TabView(selection: $selectedTab) { Tab1View(isActive: selectedTab == 0) .tabItem { Label("Tab1", systemImage: "star") } .tag(0) Tab2View(isActive: selectedTab == 1) .tabItem { Label("Tab2", systemImage: "star") } .tag(1) Tab3View(isActive: selectedTab == 2) .tabItem { Label("Tab3", systemImage: "star") } .tag(2) Tab4View(isActive: selectedTab == 3) .tabItem { Label("Tab4", systemImage: "star") } .tag(3) } } }
- 修改每个Tab视图,接收
isActive参数并控制侧边栏按钮显示:
struct Tab1View: View { let isActive: Bool var body: some View { NavigationSplitView { Text("Tab1") } detail: { Text("Detail Tab1") } .navigationSplitViewStyle(.automatic) #if os(macOS) .toolbar { ToolbarItem(placement: .navigation) { if isActive { // 保留默认的侧边栏切换按钮 Button(action: { NSApp.keyWindow?.firstResponder?.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil) }) { Image(systemName: "sidebar.left") } } else { EmptyView() } } } #endif } }
注:使用
#if os(macOS)只在macOS上生效,避免影响iPad的正常显示。
方法二:调整结构,将NavigationSplitView置于TabView外层
如果业务允许,可以把TabView放在NavigationSplitView的详情区域,这样整个窗口只会有一个侧边栏按钮,从根源上避免重复问题:
struct ContentView: View { var body: some View { NavigationSplitView { // 可根据需要设置共享侧边栏,或绑定选中标签切换侧边栏内容 Text("Shared Sidebar") } detail: { TabView() { Text("Detail Tab1").tabItem { Label("Tab1", systemImage: "star")} Text("Detail Tab2").tabItem { Label("Tab2", systemImage: "star")} Text("Detail Tab3").tabItem { Label("Tab3", systemImage: "star")} Text("Detail Tab4").tabItem { Label("Tab4", systemImage: "star")} } } .navigationSplitViewStyle(.automatic) } }
内容的提问来源于stack exchange,提问作者JYF97411
相关产品推荐
相关产品推荐

