protocol View (英文)
概览
在 SwiftUI 中,你可以将视图组合成一个层次结构,用它来描述你的 App 用户界面。视图修饰符能帮助你自定 App 视图的外观和行为。例如,你可以使用修饰符来执行以下操作:
-
为视图添加辅助功能。
-
调整视图的样式、布局和其他外观特征。
-
响应拷贝和粘贴等操作。
-
有条件地呈现模式视图,例如弹出窗口。
-
配置支持视图,例如工具栏。
由于视图修饰符是带有 View
(英文) 协议提供的行为的 Swift 方法,因此,你可以将它们应用于遵从 View
(英文) 协议的任何类型。这包括 Text
(英文)、Image
(英文) 和 Button
(英文) 等原生视图以及你定义的视图。
通过修饰符配置视图
与其他 Swift 方法一样,修饰符在实例上运行 (在本例中为某种视图) 并且可以选择性地采用输入参数。例如,你可以应用 foreground
(英文) 修饰符来设置 Text
(英文) 视图的颜色:
Text("Hello, World!")
.foregroundColor(.red) // Display red text.
修饰符将返回一个包装了原始视图的视图,并在视图层次结构中替换它。你可以将上例中的两行代码想成是解析为显示红色文本的单一视图。
尽管上述代码遵循 Swift 的规则,但刚刚接触 SwiftUI 的开发者可能不熟悉此代码的结构。SwiftUI 使用声明式方法,也就是说,你在代码中声明并配置视图的位置与视图在视图层次结构中的位置对应。有关更多信息,请参阅“声明自定视图”。
链式调用修饰符以实现复杂效果
你通常通过一个接一个地调用修饰符来以链式方式调用它们,即每个修饰符都包装了上一个修饰符的结果。例如,你可以使用 frame(width:
(英文) 修饰符将文本视图包装在具有给定宽度的隐形框中,以影响其布局,然后使用 border(_:
(英文) 修饰符围绕该框架绘制一个轮廓:
Text("Title")
.frame(width: 100)
.border(Color.gray)
你应用修饰符的顺序很重要。例如,通过以上代码得出的 border 会绘制框架完整宽度的轮廓。
如果在 border 修饰符之后指定 frame 修饰符,则 SwiftUI 仅会将 border 应用于文本视图,占用的空间绝不会超过渲染其内容所需的空间。
Text("Title")
.border(Color.gray) // Apply the border first this time.
.frame(width: 100)
将该视图包装在一个具有固定 100 点宽度的隐形框中会影响复合视图的布局,但对 border 没有影响。
配置子视图
你可以将 View
(英文) 协议定义的任何视图修饰符应用于任何具体的视图,即使是在修饰符对其目标视图没有直接影响的情况下也是如此。修饰符的影响会传播到并未显式覆盖修饰符的子视图。
例如,VStack
(英文) 实例本身的作用仅仅是垂直堆叠其他视图,它没有任何要显示的文本。因此,将一个 font(_:)
(英文) 修饰符应用于该 stack 不会对它产生任何影响。然而,font 修饰符却会应用于该 stack 的所有子视图,其中的部分视图可能会显示文本。不过,你可以通过向特定子视图添加另一个修饰符来在本地覆盖该堆叠的修饰符:
VStack {
Text("Title")
.font(.title) // Override the font of this view.
Text("First body line.")
Text("Second body line.")
}
.font(.body) // Set a default font for text in the stack.
使用特定于视图的修饰符
尽管许多视图类型依赖于标准视图修饰符来进行自定和控制,但某些视图可以定义特定于该视图类型的修饰符。此类修饰符仅适用于相应类型的视图。例如,你可以使用 Text
(英文) 定义的 bold()
(英文) 修饰符,来方便地向视图的文本添加粗体效果。尽管你可以在任何视图上使用 font(_:)
(英文),因为它是 View
(英文) 协议的一部分,但你仅能在 Text
(英文) 视图上使用 bold()
(英文)。因此,你并不能在容器视图上使用 bold 修饰符:
VStack {
Text("Hello, world!")
}
.bold() // Fails because 'VStack' doesn't have a 'bold' modifier.
此外,在应用另一个通用修饰符后,你也不能在 Text
(英文) 视图上使用它,因为通用修饰符会返回一个 opaque type (英文)。例如,padding 修饰符的返回值不是 Text
(英文),而是一个无法采用 bold 修饰符的不透明的结果类型:
Text("Hello, world!")
.padding()
.bold() // Fails because 'some View' doesn't have a 'bold' modifier.
正确的做法是将 bold 修饰符直接应用于 Text
(英文) 视图,然后添加 padding:
Text("Hello, world!")
.bold() // Succeeds.
.padding()