如何判断NavigationSplitView的可见列数及相关视图状态?
1. 判断当前可见列数
使用NavigationSplitView的columnVisibility绑定属性,它的类型是NavigationSplitViewVisibility枚举,包含三种核心状态:
.singleColumn:仅显示1列(如iPhone设备、iPad分屏窄模式).doubleColumn:显示2列(如iPad分屏中宽模式、macOS部分布局).all:显示全部3列(如iPad全屏、macOS全屏)
修改示例代码添加列数判断逻辑:
struct ContentView: View { @State private var departments = ["D1"] @State private var employees = ["E1", "E2", "E3"] @State private var selectedDepartment: String? @State private var selectedEmployee: String? // 新增列可见性绑定 @State private var columnVisibility = NavigationSplitViewVisibility.automatic var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { List(departments, id: \.self, selection: $selectedDepartment) { department in Text(department) } } content: { List(employees, id: \.self, selection: $selectedEmployee) { employee in Text(employee) } // 监听列可见性变化,判断当前列数 .onChange(of: columnVisibility) { newState in switch newState { case .singleColumn: print("当前可见1列") case .doubleColumn: print("当前可见2列") case .all: print("当前可见3列") @unknown default: break } } } detail: { if let selectedEmployee { Text(selectedEmployee) } else { Text("No employee selected") } } } }
2. 判断视图是否被推入导航栈
利用iOS 16+提供的@Environment(\.navigationStackDepth)环境变量,它返回当前导航栈的层级数:
- 层级数为0:当前视图是导航栈的根视图
- 层级数大于0:有视图被推入到当前栈中
示例用法:
struct ContentList: View { @Environment(\.navigationStackDepth) private var stackDepth let employees: [String] @Binding var selectedEmployee: String? var body: some View { List(employees, id: \.self, selection: $selectedEmployee) { employee in NavigationLink(value: employee) { Text(employee) } } .onAppear { if stackDepth > 0 { print("当前视图被推入导航栈") } else { print("当前视图是导航栈根视图") } } } }
3. 判断视图是否为iPad侧滑覆盖视图
通过组合设备类型与水平尺寸类判断:当设备是iPad,且水平尺寸类为.compact时,通常处于侧滑覆盖(Slide Over)模式。
示例代码:
struct ContentView: View { @Environment(\.horizontalSizeClass) private var horizontalSizeClass // ... 其他状态变量 var body: some View { NavigationSplitView { // sidebar内容 List(departments, id: \.self, selection: $selectedDepartment) { department in Text(department) } } content: { // content内容 List(employees, id: \.self, selection: $selectedEmployee) { employee in Text(employee) } } detail: { // detail内容 if let selectedEmployee { Text(selectedEmployee) } else { Text("No employee selected") } } .onAppear { let isSlideOver = UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact if isSlideOver { print("当前处于iPad侧滑覆盖视图") } } } }
注:若需要更精准判断,可结合
UIWindowScene的effectiveGeometry属性检查场景宽度(Slide Over标准宽度约320pt),上述方法已覆盖绝大多数场景。
内容的提问来源于stack exchange,提问作者user1046037
相关产品推荐
相关产品推荐

