You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:20:35