在你的界面中支持深色模式
在 macOS 和 iOS 中,用户可以选择采用系统范围的浅色或深色外观。深色外观也称为“深色模式”,这种外观会实施很多 App 已在采用的一种界面风格。用户可以选择他们喜爱的审美风格,也可以选择根据环境光照条件或具体时间表来切换界面。
所有 App 都应同时支持浅色和深色界面风格,但在某些位置使用特定的外观或许效果更佳。例如,对于打印的内容,你可能总是会采用浅色外观。
在更改你的代码前,请打开深色模式并查看 App 的响应情况。系统会替你完成许多工作,如果你的 App 使用标准的视图和控件,你可能不需要进行太多更改。标准视图和控件会自动更新外观来与当前的的界面风格保持一致。如果已在使用颜色和图像素材,你可以添加深色变体,而无需更改你的代码。
为你的 UI 选择自适应颜色选择可自动适应基础界面风格的颜色。浅色和深色界面使用迥然不同的调色盘。在浅色外观中表现良好的颜色或许在深色外观中难以看清,反之亦然。自适应颜色对象可以针对不同的界面风格返回不同的颜色值。
你可以通过以下两种方式创建自适应颜色对象:
选择语义颜色,而非固定颜色值。在配置 UI 元素时,选择具有 labelColor 等名称的颜色。这样的语义颜色传递颜色的预期用途,而不是具体的颜色值。在用于预期的用途时,它们会使用适合当前设置的颜色值进行渲染。有关语义颜色名称的完整列表,请参阅 NSColor (英文) 和 UIColor (英文)。
在素材目录中定义自定颜色。在你需要特定的颜色时,以颜色素材的形式创建这种颜色。在你的素材中,为浅色和深色外观指定不同的颜色值。你也可以指定颜色的高对比度版本。
你可以使用 Xcode 的素材编辑器配置自定颜色素材。在项目中添加“Color Set”(颜色集) 素材,然后配置你要修改的外观变体。使用“Any Appearance”(任意外观) 变体可以指定要在不支持深色模式的旧系统上使用的颜色值。
要从素材目录中载入颜色值,请通过名称来载入颜色:
// macOSlet aColor = NSColor(named: NSColor.Name("customControlColor"))// iOSlet aColor = UIColor(named: "customControlColor")从颜色素材创建颜色对象时,你不必在当前外观改变时重新创建这个对象。每当你为绘图设定填充或笔画颜色时,颜色对象会载入与当前环境设置匹配的颜色变体。labelColor 等语义颜色同样如此,这些颜色会自动适应当前的环境。相反,使用固定分量值创建的颜色对象不会进行调整,你必须创建新的颜色对象。
注释
对于用户的内容,请始终保留用户明确选用的颜色。例如,绘图 App 不应尝试更改用户应用到画布的颜色。自适应颜色主要用于 App 浏览器的视图和控件。
创建适合所有外观的图像确保界面中的图像在浅色和深色外观中都有良好的效果。界面在许多位置上使用图像,包括按钮、图像视图以及自定视图和控件。如果图像在外观更改后难以看清,请提供在其他外观中拥有良好效果的新图像素材。更好的是使用符号图像或模板图像,它们仅定义要渲染的形状,因此不需要对浅色、深色和高对比度环境使用不同的图像。
有关为浅色和深色界面配置图像的信息,请参阅“提供适合不同外观的图像 (英文)”。
使用特定的方法更新自定视图在用户更改系统外观时,系统会自动要求每个窗口和视图重绘自身。在这个过程中,系统会调用适用于 macOS 和 iOS 的几个常见方法 (如下表中所列) 来更新你的内容。系统会在调用这些方法前更新特征环境;这样,如果你在这些方法中进行所有对外观敏感的更改,你的 App 就能正确地更新自身。
类
适用的方法
NSView (英文)
updateLayer() (英文)
draw(_:) (英文)
layout() (英文)
updateConstraints() (英文)
UIView (英文)
traitCollectionDidChange(_:) (英文)
layoutSubviews() (英文)
draw(_:) (英文)
updateConstraints() (英文)
tintColorDidChange() (英文)
UIViewController (英文)
traitCollectionDidChange(_:) (英文)
updateViewConstraints() (英文)
viewWillLayoutSubviews() (英文)
viewDidLayoutSubviews() (英文)
UIPresentationController (英文)
traitCollectionDidChange(_:) (英文)
containerViewWillLayoutSubviews() (英文)
containerViewDidLayoutSubviews() (英文)
如果你在这些方法之外进行对外观敏感的更改,你的 App 可能无法针对当前的环境正确绘制它的内容。这时可让你的代码改为调用这些方法。例如,不要在创建时设置 NSView (英文) 对象图层的背景颜色,而应将这段代码移到视图的 updateLayer() (英文) 方法中,如下方代码示例中所示。在创建时设置背景颜色看起来似乎合理,但因为 CGColor (英文) 对象不会进行调整,在创建时设置背景颜色会使视图具有固定不变的背景颜色。将代码移到 updateLayer() 后,每当环境改变时就会自动刷新背景颜色。
override func updateLayer() { self.layer?.backgroundColor = NSColor.textBackgroundColor.cgColor // Other updates.}根据预期用途选择视觉效果材质视觉效果视图为你的背景视图增添透明度,让你的 UI 具有比背景不透明时更强的视觉深度。为确保你的内容保持可见,视觉效果视图会细微地模糊背景内容并添加振动效果,从而自动调整前景内容的颜色。系统会动态地更新这些效果,确保你的 App 内容在基础内容改变时保持可见。
以容器视图的形式在界面中使用视觉效果视图,并为它们添加子视图来代表前景内容。使用适合你所需外观的材质或效果,配置每个视觉效果视图:
在 macOS 中,根据你要如何在界面中使用该视图,使用适当的材质配置 NSVisualEffectView (英文)。例如,在将视觉效果视图用作边栏界面的背景时,可使用 NSVisualEffectView.Material.sidebar (英文) 材质进行配置。
在 iOS 中,使用特定的振动和模糊效果来配置 UIVisualEffectView (英文),以创建你想要的外观。模糊效果定义背景视图的表观厚度,振动效果则调整特定类型内容的外观,以确保它们保持可见。例如,当你的视图包含标签时,可以选择 UIVibrancyEffectStyle.label (英文) 风格或另一种与标签相关的振动选项。
重要信息
请勿使用 macOS 10.14 及更高版本中已弃用的材质,如 NSVisualEffectView.Material.light (英文),因为这些材质不能适应深色模式。这时请选择能够正确适应环境的新材质。
仅在需要时停用尽量在你的 App 中同时采用浅色和深色外观。如果支持某种外观对你 App 的全部或部分区域没有意义,你可以选择在相应的窗口或视图中停用外观更改。例如,对于 App 的打印视图,你可能总是会采用浅色外观。
你可以配置界面的全部或部分区域来停用特定的外观。你也可以对你的整个 App 采用特定的外观。有关