在 SwiftUI 中同时预览深色和浅色模式视图
· 阅读需 3 分钟
iOS 的深色和浅色模式功能在首次引入时受到广泛欢迎。如今,高质量应用几乎默认需要同时支持两种配色方案。本文不深入实现细节,而是介绍如何通过一个简单的 SwiftUI 视图结构,轻松同时预览两种模式。
iOS 框架对深色/浅色模式有很好的支持,但预览阶段往往需要手动切换。下面介绍一种更高效的方式。
强制指定配色方案
旧的(已废弃)方式是使用视图修饰符:
@inlinable public func colorScheme(_ colorScheme: ColorScheme) -> some View
这个修饰符有个关键问题:它会改变整个屏幕的配色方案,而非仅作用于所应用的视图。视图层级中多个视图同时使用时可能引发不确定行为。
因此改用新的修饰符:
@inlinable public func preferredColorScheme(_ colorScheme: ColorScheme?) -> some View
创建可复用的预览组件
利用 SwiftUI 的视图构建器(@ViewBuilder)功能,创建一个可在整个应用中复用的预览组件。ColorScheme 枚举实现了 CaseIterable 协议,可以方便地遍历所有配色方案:
struct ColorSchemesPreview<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
ForEach(ColorScheme.allCases, id: \.self) { colorScheme in
content.preferredColorScheme(colorScheme)
}
}
}
设置一个简单的预览来演示该组件:
struct ColorSchemesPreview_Previews: PreviewProvider {
static var previews: some View {
ColorSchemesPreview {
Text("Hello")
Text("world!")
}
.padding()
.previewLayout(.sizeThatFits)
}
}
注意 padding() 和 previewLayout(.sizeThatFits) 直接作用于 ColorSchemesPreview 类型。这得益于视图构建器机制,使我们能像使用系统提供的 SwiftUI 组件一样指定视图。
更进一步:使用视图修饰符
可以通过视图修饰符进一步扩展:
struct ColorSchemesViewModifier: ViewModifier {
func body(content: Content) -> some View {
Group {
ForEach(ColorScheme.allCases, id: \.self) { colorScheme in
content.preferredColorScheme(colorScheme)
}
}
}
}
在 View 上添加扩展,便于调用:
extension View {
func colorSchemesPreview() -> some View {
self.modifier(ColorSchemesViewModifier())
}
}
用视图修饰符简化 ColorSchemesPreview:
struct ColorSchemesPreview<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
content.colorSchemesPreview()
}
}
更新预览代码展示修饰符用法:
struct ColorSchemesPreview_Previews: PreviewProvider {
static var previews: some View {
Group {
Text("Hello")
Text("world!")
}
.padding()
.previewLayout(.sizeThatFits)
.colorSchemesPreview()
}
}
预览愉快!✌️
原文地址:https://peterringset.dev/articles/light-and-dark-preview
