我们将本周的文章献给那些庆祝这个受人尊敬的假期的人,无论是同时还是在iOS 13进入通用汽车的过程中。我们希望一些快速提示可以帮助您避开即将到来的阴影。

暗模式是一种外观偏好,告诉系统和参与的应用程序采用较暗的调色板。虽然应用程序默认情况下可能会在浅色背景上显示深色文本,但它可能会在深色背景上显示白色文本。

去年,Dark Mode是macOS 10.14 Mojave 杀手级功能,它与Safari 12的同期发布在整个万维网上掀起,在网站(如你的网站)和 其他浏览器中得到了稳定的采用。

在等待永恒的感觉(但仅仅是一年)之后,Dark Mode现在终于进入iPhone和iPad iOS 13.我们不再需要修改 显示调整 以限制浏览时的光污染Reddit深夜。

在iOS上采用黑暗模式

Apple在设计灵活,方便的API方面做得非常出色,并提供了优秀的文档。

当然,苹果技术面临的挑战是,如果没有告诉你“你说错了”,他们很少会承认现有技术或替代品的存在,更不用说提供一个过渡文件,它在任何方面都与每个人的方式相似在得到官方批准的API之前,我正在做的事情。(那么,你能真的责怪他们吗?

如果您遵循Apple对该信的100%指导,您几乎不必更改一行或代码以使您的应用为下周的特殊活动做好准备 。但是大多数应用程序都建立在我们为自己构建的解决方案的基础上,以弥合SDK中的差距,并且可能不清楚如何 从那里开始新的 快乐路径。

Apple对于采用Dark Mode的指导对于新项目来说非常棒,但是在为iOS 13准备现有应用程序时,并没有完全达到你应该注意的所有要点。所以不用多说了,这里有6个关于如何获取应用程序的动作项

Cancel Color Literals

在Xcode中,颜色文字 是具有前缀的代码,该前缀 在编辑器中呈现为颜色样本。例如,代码 在Xcode中呈现为#colorLiteral#colorLiteral(red: 1, green: 0.67, blue: 0, alpha: 1)。可以从Xcode 10中的媒体浏览器拖放颜色文字,Xcode 10已经与Snippets合并到Xcode 11中的新库面板中。

为了支持Xcode Playgrounds,我们引入了颜色文字和他们的堂兄,图像文字。但是不要让他们的外表欺骗你:你的应用程序的代码库中没有一个位置。

由于它们的flakey渲染,几乎可以立即排除图像文字,但只有出现黑暗模式,我们有一个强有力的理由给它们启动: 颜色文字不支持动态/命名颜色。

尝试将命名颜色拖到编辑器中会导致两个相邻的表达式 - Swift中的无效语句。如果你错误地将一个设置为视图的颜色属性,它将不会改变它在暗或亮模式下的外观。colorLiteral

$ find . -name '*.swift'  \-exec sed -i '' -E 's/#colorLiteral\(red: (.*), green: (.*), blue: (.*), alpha: (.*)\)/UIColor(red: \1, green: \2, blue: \3, alpha: \4)/ {}\;

但是在你这样做之前,你最好还是做一个更好的东西,用经得起时间考验的东西代替它。

Nix UIColor十六进制初始化器

在瑞士军刀式CocoaPod中你会发现的最常见的扩展是一个UIColor从十六进制字符串初始化的类别。有点像这样:

import SwiftySwiftColorSwift
let orange = UIColor(hex: "#FB8C00") // ?

抛开关于他们通常如何使用和实施的任何疑虑,建议您按照我们在上一节中描述的相同原因使用这些符合颜色文字的方式。

但不要担心!您仍然可以使用设计师发送的十六进制代码来定义颜色,我们将在讨论命名颜色时看到。

###查找并替换固定颜色

UIColor定义了几个按其通用名称返回颜色的类属性。这些属性在iOS 13中存在问题,因为它们不会自动调整亮度或暗度外观。例如,将标签的颜色设置为.black在默认背景下看起来很好,但是当启用暗模式时背景变为黑色时,它会难以辨认。UITableCell

为了让你的应用程序在iOS 13上为Dark Mode做好准备,你很可能想要替换以下UIColor类属性的任何实例 :

  • red

  • orange

  • yellow

  • brown

  • green

  • cyan

  • blue

  • purple

  • magenta

  • white

  • lightGray

  • gray

  • darkGray

  • black

希望除了偶尔的布局调试之外你没有使用内置的 ROYGBIV UIColor常量,但是你可能会 在某个地方的代码库中找到一些.black或者几个实例.white。

在任何情况下,支持暗模式的最简单的更改是使用system下面相应的-prefixed自适应颜色替换任何上述固定颜色属性:

您可能会注意到此表不提供黑色或白色(或棕色,但暂时忽略它)的直接对应关系。

黑色和白色没有自适应颜色,因为它们的名称在黑暗模式下不再具有描述性; 如果存在的话,几乎必须要 在深色托盘中可见。.system<wbr style="box-sizing: border-box;">Black``.white

在黑暗模式的时代,它更深入地了解色彩管理…

使用语义颜色

确保在任何外观模式下在任何设备上一致呈现UI的最佳方法是使用语义颜色,根据其功能而不是外观命名。

与动态类型如何 使用“标题”和“正文”等语义标签自动为用户的显示首选项设置最合适的字体类似,语义颜色 - 或Apple的调用 UI元素颜色 - 为您的视图和控件提供面向未来的行为。

样式化组件时,将颜色设置为UIColor下面最近的类属性:

标签颜色 填充颜色
label systemFill
secondaryLabel secondarySystemFill
tertiaryLabel tertiarySystemFill
quaternaryLabel quaternarySystemFill
文字颜色 背景颜色
placeholderText systemBackground
secondarySystemBackground
tertiarySystemBackground
链接颜色 分组的背景颜色
link systemGroupedBackground
secondarySystemGroupedBackground
tertiarySystemGroupedBackground
分色器颜色
separator
opaqueSeparator

升级本土语义颜色调色板

如果您已经考虑过在应用程序中进行颜色管理,那么您可能会采用以下策略的某种形式,即根据命名空间内或扩展名中的固定颜色定义语义颜色UIColor

例如,以下示例显示应用程序如何定义 Material UI颜色系统中的UIColor常量 并从语义类属性引用它们:UIColor

import UIKitextension UIColor {static var customAccent: UIColor { return MaterialUI.red500 }...
}fileprivate enum MaterialUI {static let orange600 = UIColor(red:   0xFB / 0xFF,green: 0x8C / 0xFF,blue:  0x00 / 0xFF,alpha: 1) // #FB8C00...
}

如果您的应用使用这样的模式,您可以使用iOS 13中的新初始化程序使其与暗模式兼容 ,如下所示:init(dynamicProvider:) UIColor

import UIKitextension UIColorstatic var customAccent: UIColor {if #available(iOS 13, *) {return UIColor { (traitCollection: UITraitCollection) -> UIColor inif traitCollection.userInterfaceStyle == .dark {return MaterialUI.orange300} else {return MaterialUI.orange600}}} else {return MaterialUI.orange600}}

使用此方法无法改变固定的材质UI颜色常量。相反,语义颜色属性提供动态颜色,使用最适合当前渲染上下文的颜色。启用暗模式时,使用浅橙色来对比较暗的调色板; 否则,行为与原始实现不变。customAccent

额外的#available检查会在实现中产生一些膨胀,但这种方法提供的灵活性是一个很小的代价。

对于奖励积分,您可以扩展此方法以支持默认和高对比度模式下的明暗模式:

// iOS >= 13
UIColor { (traitCollection: UITraitCollection) -> UIColor inswitch(traitCollection.userInterfaceStyle,traitCollection.accessibilityContrast){case (.dark, .high): return MaterialUI.orangeA200case (.dark, _):     return MaterialUI.orange300case (_, .high):     return MaterialUI.orangeA700default:             return MaterialUI.orange600}
}

不幸的是,以这种方式使用颜色属性有一个至关重要的缺点: 它们不能从Interface Builder中引用

如果您的应用使用Storyboards或XIB,最好的方法是使用颜色资源。

使用资产目录管理颜色

通过颜色资源,您可以像处理图像,数据或其他资源一样管理Xcode Asset Catalog中的颜色。

要创建颜色集,请在Xcode项目中打开资产目录,单击左下角的 + 按钮,然后选择“新颜色集”。在“属性”检查器中,选择“任意,黑暗”外观。颜色经常以表格形式表示(“#RRGGBB”); 您可以通过从“输入法”下拉列表中选择“8位十六进制”来输入此表单中的颜色。

在这里,我们和以前一样,除了UIColor不像orange300代码中那样定义固定常量,我们在颜色集本身中设置它们。现在,当需要通过现有的语义类属性引用颜色资源时,我们可以使用UIColor命名的初始化程序:

extension UIColor {@available(iOS 11, *)var customAccent: UIColor! {return UIColor(named: "Accent")}
}

单个应用可以有多个资产目录。考虑为您的颜色资产创建一个单独的颜色

您对颜色资产的看法很大程度上取决于您对专业Xcode文档编辑的偏好或不尊重。有些人喜欢在代码中拼写出所有内容,而其他人则喜欢定制用户界面提供的功能,例如Xcode为彩色套装提供的功能。

事实上,您对色彩资产的看法可能伴随着您对Storyboards的感受 - 这很方便,因为色彩资产的杀手级功能是它们可以在Interface Builder中引用。 (如果你不在IB团队,那么你可以安全地跳过整个讨论。)

替换XIB和Storyboard中的“自定义颜色”实例

Interface Builder中的“自定义颜色”选项调出了macOS系统原生颜色选择器,遇到的问题与我们之前谈到的颜色文字和固定颜色相同。如果您希望X13驱动的视图在iOS 13上看起来很好,则需要迁移到命名颜色。

这可以轻松完成:选择场景中的任何组件,并且可以使用资产目录中定义的相同命名颜色设置其颜色属性。

对于一个小项目,这可以在一小时内手动完成所有屏幕。但是,对于更大的应用程序,这是一个您想要自动化的过程。

XIB解剖学

在幕后,XIB和Storyboard文件只是像任何其他文件一样的XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" <#...#>><device id="retina6_1" orientation="portrait"><adaptation id="fullscreen"/></device><dependencies><deployment identifier="iOS"/><plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/><capability name="Safe area layout guides" minToolsVersion="9.0"/><capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/></dependencies><scenes><!--View Controller--><scene sceneID="nsh-ips-ter"><objects><viewController id="dar-kmo-de1" customClass="ViewController" customModule="NSHipster" customModuleProvider="target" sceneMemberID="viewController"><view key="view" contentMode="scaleToFill" id="mai-nv-iew"><rect key="frame" x="0.0" y="0.0" width="414" height="896"/><color key="backgroundColor" red="1" green="0.69019607843137254" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/></view></viewController><placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/></objects></scene></scenes>
</document>

我们不想手工写这个,但这里没有什么太神秘的了。

因此,请考虑使用Xcode将主视图的自定义背景颜色切换为命名颜色时会发生什么:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" <#...#>><device <#...#>/><dependencies><#...#><capability name="Named colors" minToolsVersion="9.0"/> <!-- ❶ --></dependencies><scenes><!-- scenes.scene.objects.viewController.view --><#...#><view key="view" contentMode="scaleToFill" id="mai-nv-iew"><#...#><color key="backgroundColor" name="Accent"/> <!-- ❷ --></view></scenes><resources><namedColor name="Accent"> <!-- ❸ --><color red="1" green="0.69019607843137254" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/></namedColor></resources>
</document>
  • "Named colors"添加了一个新功能作为打开文档的依赖项(Xcode使用它来确定它是否可以编辑由较新版本创建的文件)。
  • 的red,green,blue,和alpha所述上部件color元件由单个替换name属性。
  • 相应的元素已添加到顶级元素中。namedColorresources

基于这样的认识,我们应该知道足以让这个改变集体 用我们自己的工具!

查找所有自定义颜色

以下示例使用XMLStarlet命令行工具使用XPath查询XIB和Storyboard文件 。
您可以自己安装它并使用Homebrew跟随 :$ brew install xmlstarlet

迁移故事板和XIB用于暗模式时的第一个业务是查找自定义颜色的所有实例。您可以手动浏览每个并单击每个可视元素…或者您可以运行以下命令:

$ find . -name '*.xib' -or -name '*.storyboard' \-exec echo {} \;        \-exec xmlstarlet sel -t \-m "//color[@colorSpace='custom']" -c . -n  {} \;Main.storyboard
<color red="1" green="0.69019607843137254" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>

此命令打印每个文件的名称,后跟它color找到的每个自定义未命名元素(由属性表示)。colorSpace="custom"

结果列表可作为下一阶段攻击的战斗计划:

寻找每种不同的自定义颜色

应用程序倾向于在其视图中重复使用一小组颜色 - 正如他们应该的那样!通过运行以下命令,您可以在每个XIB或Storyboard中生成每个自定义颜色的已排序,唯一的列表:

$ find . -name '*.xib' -or -name '*.storyboard' \-exec xmlstarlet sel -t \-m "//color[@colorSpace='custom']"  \-v "concat( @red,'  ',@green,'  ',@blue,'  ',@alpha)" -n  {} \; \| sort -u1  0.69019607839999997  0.0  1

有些条目可能是相同的,在彼此的小三角形内(因为,你知道…浮点数)。为了解释这一点,并将输出转换为更容易使用的东西,您可以将输出写入文件并使用类似这样的Ruby脚本处理它:

colors = File.readlines('distinct_colors.txt').map do |line|components = line.strip.split(/\s+/).flat_map(&:to_f)red, green, blue = components[0..2].map{ |c| (c * 255).floor }alpha = (components.last * 100).floor[red, green, blue, alpha]
endcolors.uniq.each do |color|puts "#%02X%02X%02X (%d%%)" % color
end

从这里开始,最后一步是将每组RGBA值映射 到要替换它的相应命名颜色。

如果您的数据集很大,或者您只是不相信您的眼睛正确量化这些颜色,您可以使用聚类算法为您执行此操作。
您可能熟悉 k -means聚类,但这需要我们提前指定目标簇数。如果您不知道有多少组有先验, “基于密度的噪声应用空间聚类” DBSCAN 可以是一个不错的选择。
Ruby方便地有一个 适合我们目的的宝石*

require 'dbscan'dbscan = DBSCAN(colors, epsilon: 8, min_points: 1, distance: :euclidean_distance)
puts dbscan.results

为获得最佳效果,请 在聚类前将RGBA值转换为 具有感知均匀性的色彩空间。

替换自定义颜色
在这一点上,我们已经远远超出了shell单行似乎是个好主意的地步。所以这里是我们编写的Ruby脚本,它使我们理解的所有更改都在Interface Builder中用命名颜色替换自定义颜色时发生:

我无法保证此脚本的正确性,因此使用它需要您自担风险。

require 'nokogiri'def name_for_rgba_components(red, green, blue, alpha)case format('#%02X%02X%02X%02X', red, green, blue, alpha)# Return named color matching RGBA components# e.g. "#F8CB00FF" => "Accent"end
enddef name_for_white_and_alpha_components(white, alpha)# Return named color matching white and alpha components# e.g. 0.9 => "Off-White"
end# Process each Storyboard and XIB file
Dir['**/*.{storyboard,xib}'].each do |xib|doc = Nokogiri::XML(File.read(xib))names = []# Collect each custom color and assign it a namedoc.xpath('//objects//color').each do |color|next if color['name']name = nilcolor_space = color['colorSpace']color_space = color['customColorSpace'] if color_space == 'custom'case color_spacewhen 'sRGB', 'calibratedRGB'components = color.attributes.values_at('red', 'green', 'blue', 'alpha').map(&:value).map(&:to_f).map { |c| c * 255 }name = name_for_rgba_components(*components)when 'genericGamma22GrayColorSpace', 'calibratedWhite'components = color.attributes.values_at('white', 'alpha').map(&:value).map(&:to_f)name = name_for_white_and_alpha_components(*components)endnext unless namenamed_color = doc.create_element('color',key: color['key'],name: name)color.replace(named_color)names << nameend# Proceed to the next file if no named colors were foundnext if names.empty?# Add the named color capability as a document dependencydependencies = doc.at('/document/dependencies') ||doc.root.add_child(doc.create_element('dependencies'))unless dependencies.at("capability[@name='Named colors']")dependencies << doc.create_element('capability',name: 'Named colors',minToolsVersion: '9.0')end# Add each named color to the document resourcesresources = doc.at('/document/resources') ||doc.root.add_child(doc.create_element('resources'))names.uniq.sort.each do |name|next if resources.at("namedColor[@name='#{name}']")resources << doc.create_element('namedColor', name: name)end# Save the changesFile.write(xib, doc.to_xml(indent: 4, encoding: 'UTF-8'))
end

你怎么看?请通过加我们的交流群 点击此处进交流群 ,来一起交流或者发布您的问题,意见或反馈。

谢谢阅读~点个赞再走呗!?

原文地址 https://nshipster.com/dark-mode/

iOS知识分享 — iOS 13上的暗模式相关推荐

  1. 知识分享之PostgreSQL——数据库中的模式(Schema)

    知识分享之PostgreSQL--数据库中的模式(Schema) 背景 日常我们开发时,我们会遇到各种各样的奇奇怪怪的问题(踩坑o(╯□╰)o),这个常见问题系列就是我日常遇到的一些问题的记录文章系列 ...

  2. ios技术分享| iOS 发布 framework 到 Cocoapods 以及常见问题

    前言 CocoaPods 是一个用来管理 Xcode 依赖库的项目,通过 CocoaPods,我们可以直观集中和 自动化地管理我们项目的第三方库. 本篇文章讲述如何将 framework 发布到 Co ...

  3. ios单应用模式_如何为iOS 13暗模式设置应用

    ios单应用模式 Apple launched the much-awaited iOS 13 updates globally on September 19 across all iPhones ...

  4. mac 恢复模式获取密码_如何在Mac上为所有网站获取暗模式

    mac 恢复模式获取密码 Khamosh Pathak Khamosh Pathak Now that macOS Mojave has a dark mode, wouldn't it be nea ...

  5. ddns 被解析为127.0.0.1_我为北京冬奥加油,2020.2.1-2.10冬奥知识分享

    2020.02.01 中国冬梦,世界飞跃,我是果雪儿小小志愿者仇懿琛,我为北京冬奥加油,今天冬奥知识分享--冬奥会历史上那些非凡而又卓越的运动员(十一)明星运动员:米特迈尔 第十二届冬季奥运会 时间: ...

  6. 企业知识分享系统的设计与实现

    摘  要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息.为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代, ...

  7. 知识图谱 | (2)知识图谱技术综述(上)

    原文地址 摘要: 知识图谱技术是人工智能技术的重要组成部分,其建立的具有语义处理能力与开放互联能力的知识库,可在智能搜索.智能问答.个性化推荐等智能信息服务中产生应用价值. 该文在全面阐述知识图谱定义 ...

  8. 知识分享之Golang——使用gorm时进行执行自定义SQL的几种方式

    知识分享之Golang--使用gorm时进行执行自定义SQL的几种方式 背景 知识分享之Golang篇是我在日常使用Golang时学习到的各种各样的知识的记录,将其整理出来以文章的形式分享给大家,来进 ...

  9. 360浏览器极速模式自动_浏览器正在为网站带来自动暗模式

    360浏览器极速模式自动 nalyvme/Shutterstock.comnalyvme / Shutterstock.com Dark mode is now everywhere, includi ...

最新文章

  1. Ubuntu 修改时区和时间
  2. No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv7s)
  3. java网格画线_java 网格输出的类--练习 stream
  4. css如何各种中文字体如雅黑、黑体、宋体、楷体等等
  5. 制作网页版电子时钟特效
  6. [转载] 高阶函数和柯里化
  7. 如何更好的优化MySQL数据库
  8. Wireshark分析SMTP、POP3协议
  9. windows vista本该有却没有的功能
  10. 转发文章【我们是怎样一步步的走向平庸的】
  11. arcgis 出图背景_ArcGIS入门教程来袭,零基础的同学快看过来!
  12. Android蓝牙打印机,带你真正了解各种打印格式
  13. 贰零贰壹·陆·伍·|比赛|·|创客|:第二十届自治区青少年机器人竞赛心得总结
  14. L1 批判思维 - 03信息甄别 - 第一章:被动接受时,学会筛选信息 1.1 追踪信息来源
  15. 【C语言程序设计】实验 10
  16. 国内十大精选正规现货交易平台排名榜单(2023口碑榜)
  17. idea跳到下一个断点_IDEA---断点调试Debug
  18. 有没有比较好的建站系统可推荐?
  19. 什么是中台?一篇带你了解中台的概念
  20. 用Python实现BT种子转化为磁力链接

热门文章

  1. 基于swiftype应用于Hexo-Yilia-主题的站内搜索引擎
  2. 360浏览器代码修改浏览模式
  3. 计算机软考答题卡填涂格式,全国计算机软考网络工程师填涂答题卡须知
  4. 成都计算机职业学院排名,成都市计算机专业职业院校排名
  5. 基于javaweb的毕设基于java的系统设计与开发
  6. 技术人“结构化思维”训练的一点想法和实践
  7. python垃圾邮件识别_Python 手写朴素贝叶斯分类器检测垃圾邮件/短信
  8. 创客匠人用户分组:用户定向运营,不浪费一滴流量
  9. layui搭建后台管理系统
  10. html目录ppt,PPT目录内容怎么写?