如果您的应用程序使用两列或三列NavigationView
,或者在某些情况下有多列的应用程序,而在其他情况下使用单列的应用程序(这在iPhone和iPad上运行的应用程序是典型的),请切换到NavigationSplitView
。
而不是使用两列导航视图:
NavigationView { // This is deprecated.
/* column 1 */
/* column 2 */
}
或者
NavigationView { // This is deprecated.
/* column 1 */
/* column 2 */
/* column 3 */
}
使用init(sidebar:detail:)
初始化器创建一个导航拆分视图,该视图具有显式边栏和详细内容:
NavigationSplitView {
/* column 1 */
} detail: {
/* column 2 */
}
或者使用
NavigationSplitView {
/* column 1 */
} content: {
/* column 2 */
} detail: {
/* column 3 */
}
如果使用具有isActive
输入参数的NavigationLink
初始化器之一执行编程导航,请将自动化移动到封闭堆栈。要做到这一点,请将导航链接更改为使用init(value:label:)
初始值设定项,然后使用一个接受路径输入的导航堆栈初始化项,如init(path:root:)
。
例如,如果您有一个导航视图,其中包含响应单个状态变量激活的链接:
@State private var isShowingPurple = false
@State private var isShowingPink = false
@State private var isShowingOrange = false
var body: some View {
NavigationView { // This is deprecated.
List {
NavigationLink("Purple", isActive: $isShowingPurple) {
ColorDetail(color: .purple)
}
NavigationLink("Pink", isActive: $isShowingPink) {
ColorDetail(color: .pink)
}
NavigationLink("Orange", isActive: $isShowingOrange) {
ColorDetail(color: .orange)
}
}
}
.navigationViewStyle(.stack)
}
当代码的其他部分将状态变量之一设置为true时,具有匹配标签的导航链接会响应激活。
将此重写为采用路径输入的导航堆栈:
@State private var path: [Color] = [] // Nothing on the stack by default.
var body: some View {
NavigationStack(path: $path) {
List {
NavigationLink("Purple", value: .purple)
NavigationLink("Pink", value: .pink)
NavigationLink("Orange", value: .orange)
}
.navigationDestination(for: Color.self) { color in
ColorDetail(color: color)
}
}
}
此版本使用NavigationDestination(for:destination:)
视图修改器将显示的数据从相应的视图分离。这使得路径数组可以表示堆栈上的每个视图。对数组所做的更改会影响容器当前显示的内容,以及人们在堆栈中导航时遇到的情况。如果使用NavigationPath
来存储路径信息,而不是简单的数据集合,则可以支持更复杂的编程导航。有关详细信息,请参阅NavigationStack
。
如果您对使用带有aselection输入参数的<wbr data-v-88c637be="">Navigation
初始化器之一的List
元素执行编程导航,则可以将选择移动到列表中。例如,假设您有一个导航视图,其中包含响应selection
状态变量而激活的链接:
let colors: [Color] = [.purple, .pink, .orange]
@State private var selection: Color? = nil // Nothing selected by default.
var body: some View {
NavigationView { // This is deprecated.
List {
ForEach(colors, id: \.self) { color in
NavigationLink(color.description, tag: color, selection: $selection) {
ColorDetail(color: color)
}
}
}
Text("Pick a color")
}
}
使用相同的属性,您可以将主体重写为:
var body: some View {
NavigationSplitView {
List(colors, id: \.self, selection: $selection) { color in
NavigationLink(color.description, value: color)
}
} detail: {
if let color = selection {
ColorDetail(color: color)
} else {
Text("Pick a color")
}
}
}
列表与导航逻辑协调,以便更改代码另一部分中的选择状态变量激活具有相应颜色的导航链接。同样,如果有人选择与特定颜色关联的导航链接,列表会更新代码其他部分可以读取的选择值。
NavigationSplitView
您创建一个包含两列或三列的导航拆分视图,通常将其用作Scene
中的根视图。人们在前列中选择一个或多个项目,以便在后续列中显示有关这些项目的详细信息。
要创建双列导航拆分视图,请使用init(sidebar:detail:)
初始化器:
@State private var employeeIds: Set<Employee.ID> = []
var body: some View {
NavigationSplitView {
List(model.employees, selection: $employeeIds) { employee in
Text(employee.name)
}
} detail: {
EmployeeDetails(for: employeeIds)
}
}
在上面的示例中,导航拆分视图与第一列中的List
协调,因此当人们进行选择时,详细信息视图会相应更新。您对选择属性所做的编程更改也会影响列表外观和显示的详细信息视图。
要创建三列视图,请使用init(sidebar:content:detail:)
初始化器。第一列中的选择影响第二列,第二列中的选择影响第三列。例如,您可以显示部门列表、所选部门的员工列表以及所有选定员工的详细信息:
@State private var departmentId: Department.ID? // Single selection.
@State private var employeeIds: Set<Employee.ID> = [] // Multiple selection.
var body: some View {
NavigationSplitView {
List(model.departments, selection: $departmentId) { department in
Text(department.name)
}
} content: {
if let department = model.department(id: departmentId) {
List(department.employees, selection: $employeeIds) { employee in
Text(employee.name)
}
} else {
Text("Select a department")
}
} detail: {
EmployeeDetails(for: employeeIds)
}
}
还可以在列中嵌入NavigationStack
。点击或单击出现在前一列中的NavigationLink
将设置堆栈在其根视图上显示的视图。激活同一列中的链接会将视图添加到堆栈中。无论哪种方式,链接都必须呈现堆栈具有相应navigationDestination(for:destination:)
修饰符的数据类型。
在watchOS
和tvOS
上,以及像iPhone
或iPad
上的SlideOver
这样的窄尺寸,导航拆分视图将其所有列折叠为堆栈,并显示显示有用信息的最后一列。例如,上面的三列示例显示了要开始的部门列表、某人选择部门后部门中的员工以及某人选择员工时的员工详细信息。对于列表中具有NavigationLink
实例的行,当处于折叠状态时,该列表会绘制披露V形。
控制柱可见性
通过创建NavigationSplitViewVisibility
类型的State
值,可以以编程方式控制导航拆分视图列的可见性。然后将绑定传递给相应的初始值设定项-两列的init(columnVisibility:sidebar:detail:)
,或三列的init(columnVisibility:sidebar:content:detail:)
。
以下代码更新了上面的第一个示例,以便在视图出现时始终隐藏第一列:
@State private var employeeIds: Set<Employee.ID> = []
@State private var columnVisibility =
NavigationSplitViewVisibility.detailOnly
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
List(model.employees, selection: $employeeIds) { employee in
Text(employee.name)
}
} detail: {
EmployeeDetails(for: employeeIds)
}
}
拆分视图在将其列折叠到堆栈中时忽略可见性控件。
自定义拆分视图
要在导航拆分视图中指定首选列宽,请使用navigationSplitViewColumnWidth(_:)
修饰符。要设置列的最小、最大和理想大小,请使用navigationSplitViewColumnWidth(min:ideal:max:)
。可以在每列中指定不同的修饰符。导航拆分视图尽可能适应您指定的首选项,但可能会根据其他约束进行调整。
要指定导航拆分视图中的列如何交互,请将navigationSplitViewStyle(_:)
修饰符与NavigationSplitView Style值一起使用。例如,您可以指定是强调细节列,还是使所有列的突出度相等。
NavigationSplitViewVisibility
使用此类型的值来控制NavigationSplitView
的列的可见性。使用此类型的值创建一个State
属性,并在创建导航拆分视图时将绑定传递给init(columnVisibility:sidebar:detail:)
或init(columnVisibility:sidebar:content:detail:)
初始值设定项。然后,您可以修改代码中其他位置的值以:
- 使用
detailOnly
隐藏除尾随列之外的所有列。 - 使用
doubleColumn
隐藏三列导航拆分视图的前导列。 - 显示所有列。
- 使用
automatic
依赖当前上下文的自动行为。
网友评论