iOSBlog
iOSBlog copied to clipboard
SB 是如何适配黑暗模式的?

- 更新:2020-05-11-23:30:19。
- 注意:查看正文前,请先查看文末的评论,以确认是否有勘误。
最近@iTeaTime(技术清谈) 群里聊到了 SB、XIB 的暗黑模式适配问题,聊天内容如下:

今天详细介绍下方法: 内容来自 Table of Contents for iOS Programming: The Big Nerd Ranch Guide, 7th Edition 由@iTeaTime(技术清谈) 翻译整理。
适应黑暗模式
iOS 支持全系统的暗黑外观,称为暗黑模式,Apple 设计指南上建议所有 iOS 应用应该遵循用户的显示模式的设置偏好。今天我们将学习如何适配暗黑模式:
适配前:

我们的任务: 适配后:

让我们开始吧!
正文
首先我们来看看 Demo 目前在暗模式下的样子。
在应用程序仍在运行的情况下,点击Xcode调试工具栏中的
按钮,打开环境覆盖菜单,将环境更改为暗模式。 打开界面风格开关并选择暗模式。
选择黑暗模式环境覆盖。

浏览应用,注意到 Demo 自动对黑暗模式的适应很好。
黑暗模式下的Demo。

默认情况下,系统提供的视图--如UILabel、UITextField和UIView--会在绘制时使用动态颜色。动态颜色提供了不同的值,这取决于它们是以浅色还是深色的形式出现。(它们也会根据一些可访问性选项(如增加对比度)稍作改变。 Interface Builder的颜色选择器中的大部分颜色都是动态颜色。在颜色选择器中,请注意标签颜色和系统背景颜色。Label Color是标签的默认文本颜色;浅色外观为黑色,深色外观为白色。系统背景色与此相反;浅色外观时为白色,深色外观时为黑色。由于我们没有更改 Demo 中视图的默认颜色,因此应用程序会适当地响应于暗模式。
界面生成器中的动态颜色

你也可以在代码中使用这些颜色。标签颜色映射到 UIColor.label,系统背景颜色映射到 UIColor.systemBackground。查看 UIColor 文档中的完整值列表。
动态颜色取决于当前的特征集合,以提供适应性。特征集合是 UITraitCollection 的一个实例,它可以帮助决定视图的外观,其属性如下:
userInterfaceIdiom |
应用程序所运行的设备类型,如iPhone、iPad、Apple TV或CarPlay设备 |
|---|---|
| userInterfaceStyle | 明(Light Mode)或暗(Dark Mode)模式 |
| userInterfaceLevel | base level(用于全屏视图)或 elevated level (用于非全屏视图,如模态、弹出式窗口和分屏视图中的应用程序等)。 |
UIView 和 UIViewController 的实例都有一个 traitCollection 属性,可以用来访问这些属性。另一个访问 trait collection 的方便方法是 UITraitCollection 的 current 属性,它是由 UIKit 框架自动设置的。
动态颜色使用了当前的 trait collection ,根据界面风格和级别来决定返回哪种颜色。UIKit 包含了几个系统级的动态颜色。背景色有三种变体:主色、次色和三级色(primary, secondary, and tertiary)。
这些颜色可以让你结构化你的应用程序的视图层次结构。例如,当使用深色外观的 systemBackgroundColor 时,系统将为全屏(base level)视图使用纯黑色,为非全屏(elevated level )视图使用深灰色。你可以使用 trait collection 属性为你的界面做同样的事情。
背景色变体

有四个级别的文字颜色,可以让你强调各元素相对于其他元素的重要性。一级色用于标题,二级色用于副标题,三级色和四级色用于其他文字。您可以将这些颜色用于其他目的,但在使用这些颜色时,了解颜色的层次结构是很重要的。
虽然 Demo 对暗色模式反应良好,但让我们来更新一下它的界面,使用一些不同的颜色来给App增添一些色彩。要做到这一点,你将创建一些自定义颜色,然后在不同的界面元素上使用这些颜色。
为 Asset Catalog 添加颜色
你在 Quiz 和 WorldTrotter 应用程序中向Asset Catalog添加了图像。现在,你将使用 Asset Catalog 来添加颜色。使用 Asset Catalog 可以让你给这些颜色命名,这些颜色可以在界面生成器中以及代码中引用,更重要的是,你将能够自定义颜色,以便于明暗两色的外观。
打开Assets.xcasse 在左下角,单击
,选择新建颜色集。
添加新的颜色

双击侧边栏中的颜色,并命名为 "主品牌填充色"。这个颜色将被用作整个应用程序的背景。在颜色仍被选中的情况下,打开它的属性检查器。从 "外观 "下拉菜单中,选择 "任意,深色"。注意,在目录中会出现一个额外的颜色选项。
添加另一个颜色外观

现在你可以更新颜色值了。如果界面是暗色外观(Dark Appearance),将使用暗色外观的颜色。否则,将使用任意外观(Any Appearance)颜色。
选择 "任意外观" 框,打开其属性检查器。在颜色部分,将输入法设置为8位(0-255)。然后,将红色、绿色和蓝色值分别改为248、248和253。
现在选择暗色外观框,并将红色、绿色和蓝色值分别设置为25、25和42。
创建了主填充颜色后,重复相同的步骤,再创建两个你将在应用程序中使用的颜色。使用的值见下表。
颜色表
| Name | Any Appearance | Dark Appearance |
|---|---|---|
| Secondary Brand Fill Color | Red 236 Green 235Blue 255 | Red 45Green 42 Blue 75 |
| Brand Accent Color | Red 240 Green 79 Blue 0 | Red 255Green 84Blue 0 |
你可能会注意到, Brand Accent Color 和其他颜色非常相似,深色的外观颜色只比浅色的外观颜色浅一点。非填充色通常都是这样的情况。虽然任何橙色(在本例中)都会与白色、灰色或黑色的背景形成对比,但将深色外观色设置得更浅一点,会让它在较深的背景填充色上有额外的 "流行 "效果(反之亦然)。
使用自定义动态颜色
创建了三种动态颜色后,是时候让它们派上用场了。先从更新 ItemsViewController 开始。
打开 Main.storyboard,找到 Demo 的 scene。选择表视图,打开其属性检查器。向下滚动到视图部分,打开背景下拉菜单。你应该会在这个下拉菜单中看到一个新的部分,标签为 "命名的颜色"。从这个列表中选择主品牌填充色。现在对表格视图单元格进行同样的操作。选择它,打开属性检查器,将其背景颜色改为主品牌填充色。
颜色选择器中的命名颜色

目前为止,我们来看看界面的样子。你可以使用视图为菜单改变画布显示的是浅色风格还是深色风格的外观。展开 "视图为菜单",选择深色界面风格。
现在,更新导航栏。找到画布上的导航控制器,选择其界面顶部的导航栏。打开它的属性检查器,在导航栏部分找到导航栏色调选项。打开颜色菜单,选择 "次要品牌填充颜色"。
设置条形色条的色调
为了让 ItemsViewController 好看,最后要更新的颜色是全局色调颜色。每个应用程序都有一个色调颜色,它是用来给交互式界面元素着色的,如条形按钮项、警报和动作表动作标题以及标签栏项。
要更改全局色调颜色,请点击检查器中的
选项卡或使用键盘快捷键Option-Command-1打开文件检查器。向下滚动到界面生成器文档部分,找到全局色调选项。打开其颜色菜单,选择 "Brand Accent Color"。
设置全局色调颜色
请注意,很多之前默认的蓝色调的界面元素现在都变成了 brand accent color 。
画布上的全局色调

在处理好了ItemsViewController的颜色后,让我们把注意力转向DetailViewController。
选择DetailViewController的背景视图,打开它的属性检查器,将其背景颜色改为 Primary Brand Fill Color。然后选择工具栏,打开它的属性检查器,并将其条形色改为 Secondary Brand Fill Color 。这样你的界面会是这样的:
更新了 "DetailViewController "颜色。

文字字段的背景颜色可以改进一下,使其在背景视图中显得更加突出。让我们把它们更新一下,让它们变得更加赏心悦目一些。
选择名称文本字段,打开其属性检查器。向下滚动到视图部分,将背景改成 Tertiary System Fill Color。文档中说, Tertiary System Fill Color 适合填充大型形状,如输入字段、搜索栏、按钮等。文本字段就是输入字段,所以这个颜色选择很好用。对其他两个文本字段重复同样的步骤。完成后,界面看起来就会像:
*完成后的APP颜色

构建并运行该项目。浏览应用程序,使用环境覆盖项在浅色和深色外观之间切换。Demo 对这两种外观的新颜色都有很好的响应。
我们已经完成了暗黑模式下的主题色适配!

原文地址:https://github.com/ChenYilong/iOSBlog/issues/30
据说点了"在看"的童鞋
明早起床,皮肤变白、不再暗黑!
"在看"👇👇