Author | hite, at present in the netease strictly selected iOS group, main work contents webview, spare time to write some thoughts product planning, all kinds of game players clouds
As the biggest new feature of iOS 13, dark mode brings new changes in design system, color, material, system controls, SF Symbols and other aspects from the perspective of designers. For developers, we’re familiar with adaptation;
• Screen size
• Screen orientation
• View rendering (viewDidLoad and viewDidAppear)
• iOS SDK adaptation
Equal fit dimension, and then another dimension,
• Appearance mode (Dark or Light)
For Dark mode adaptation, we need to deal with the logic of images, backgrounds, padding, text and dividers. The first is that designers must design two different color schemes for two kinds of appearance. When the two schemes were delivered to the developers, we also needed to apply different colors according to different looks. Fortunately, developers can create a wrapper that encapsulates this layer of logic and hides the internal logic for other developers to use. For this purpose, iOS provides passive adaptation — dynamic colors;
let backgroundColor = UIColor { (trainCollection) -> UIColor in if trainCollection.userInterfaceStyle == .dark { return UIColor.black } else { return UIColor.white }}view.backgroundColor = backgroundColor
Copy the code
And active adaptation, we can call in UIViewController or UIView traitCollection. UserInterfaceStyle to obtain the current view of style;
if trainCollection.userInterfaceStyle == .dark { // Dark} else { // Light}
Copy the code
Or use the Name Assets technology to configure in advance and let the system switch automatically.
In practice, it’s a bit of a hassle. To further simplify the amount of code for adaptation, Apple specifically provides a mechanism called DynamicColorProvider, which has some dynamic colors built in. A “font color” that refers to white in dark mode and black in light mode.
textLabel.textColor = UIColor.labelColor
Copy the code
In iOS Design System, text, background and ICONS on the interface are layered with information, and different colors are needed accordingly. Take text colors as an example. IOS 13 has four built-in layers;
• UIColor.labelColor,
• UIColor.secondaryLabelColor,
• UIColor.tertiaryLabelColor,
• UIColor. QuaternaryLabelColor
LabelColor is a primary word color that provides the highest contrast and is used for the most important content elements, such as the main heading of content. And SecondaryLabelColor can be used for subheadings, TertiaryLabelColor for input box placeholder text, and QuaternaryLabelColor for disabled text.
Using dynamic colors is the easiest way to fit dark mode. But it has a problem: what is the color value of labelColor? What’s dark? What’s light?
LabelColor’s answer is simple, but iOS introduces a total of 24 dynamic colors with 48 color values. When it was really merged with our App’s own style system, designers and developers didn’t know that the built-in dynamic color was compatible with the App itself?
When I made the adaptation for 9 Star Browser, my head was too big, I knew the UIColor. SeparatorColor can automatically change color, but whether the color value is in harmony with my App style, there is no color value for me to compare. When I tried to find a complete set of DynamicColor values online, I couldn’t find them for a while. So I’m gonna make my own.
Color matching in Dark mode
color | #hex | rgba |
---|---|---|
labelColor | #FFFFFFFF | Rgba (255255255,1.00) |
secondaryLabelColor | #EBEBF599 | Rgba (235235245,0.60) |
tertiaryLabelColor | #EBEBF54C | Rgba (235235245,0.30) |
quaternaryLabelColor | #EBEBF52D | Rgba (235235245,0.18) |
linkColor | #0984FFFF | Rgba (9132255,1.00) |
placeholderTextColor | #EBEBF54C | Rgba (235235245,0.30) |
separatorColor | # 54545899 | Rgba (84,84,88,0.60) |
opaqueSeparatorColor | #38383AFF | Rgba (56,56,58,1.00) |
systemBackgroundColor | #000000FF | Rgba (0,0,0,1.00) |
secondarySystemBackgroundColor | #1C1C1EFF | Rgba (28,28,30,1.00) |
tertiarySystemBackgroundColor | #2C2C2EFF | Rgba (44,44,46,1.00) |
systemGroupedBackgroundColor | #000000FF | Rgba (0,0,0,1.00) |
secondarySystemGroupedBackgroundColor | #1C1C1EFF | Rgba (28,28,30,1.00) |
tertiarySystemGroupedBackgroundColor | #2C2C2EFF | Rgba (44,44,46,1.00) |
systemFillColor | #7878805B | Rgba (120120128,0.36) |
secondarySystemGroupedBackgroundColor | #1C1C1EFF | Rgba (28,28,30,1.00) |
tertiarySystemGroupedBackgroundColor | #2C2C2EFF | Rgba (44,44,46,1.00) |
systemFillColor | #7878805B | Rgba (120120128,0.36) |
secondarySystemFillColor | # 78788051 | Rgba (120120128,0.32) |
tertiarySystemFillColor | #7676803D | Rgba (118118128,0.24) |
quaternarySystemFillColor | #7676802D | Rgba (118118128,0.18) |
systemRedColor | #FF453AFF | Rgba (255,69,58,1.00) |
systemGreenColor | #30D158FF | Rgba (48209,88,1.00) |
systemBlueColor | #0A84FFFF | Rgba (10132255,1.00) |
systemOrangeColor | #FF9F0AFF | Rgba (255159,10,1.00) |
systemYellowColor | #FFD60AFF | Rgba (255214,10,1.00) |
systemPinkColor | #FF375FFF | Rgba (255,55,95,1.00) |
systemPurpleColor | #BF5AF2FF | Rgba (191,90,242,1.00) |
systemTealColor | #64D2FFFF | Rgba (100210255,1.00) |
systemIndigoColor | #5E5CE6FF | Rgba (94,92,230,1.00) |
systemGrayColor | #8E8E93FF | Rgba (142142147,1.00) |
systemGray2Color | #636366FF | Rgba (99,99,102,1.00) |
systemGray3Color | #48484AFF | Rgba (72,72,74,1.00) |
Color matching in light color mode
color | #hex | rgba |
---|---|---|
labelColor | #000000FF | Rgba (0,0,0,1.00) |
secondaryLabelColor | #3C3C4399 | Rgba (60,60,67,0.60) |
tertiaryLabelColor | #3C3C434C | Rgba (60,60,67,0.30) |
quaternaryLabelColor | #3C3C432D | Rgba (60,60,67,0.18) |
linkColor | #007AFFFF | Rgba (0122255,1.00) |
placeholderTextColor | #3C3C434C | Rgba (60,60,67,0.30) |
separatorColor | #3C3C4349 | Rgba (60,60,67,0.29) |
opaqueSeparatorColor | #C6C6C8FF | Rgba (198198200,1.00) |
systemBackgroundColor | #FFFFFFFF | Rgba (255255255,1.00) |
secondarySystemBackgroundColor | #F2F2F7FF | Rgba (242242247,1.00) |
tertiarySystemBackgroundColor | #FFFFFFFF | Rgba (255255255,1.00) |
systemGroupedBackgroundColor | #F2F2F7FF | Rgba (242242247,1.00) |
secondarySystemGroupedBackgroundColor | #FFFFFFFF | Rgba (255255255,1.00) |
tertiarySystemGroupedBackgroundColor | #F2F2F7FF | Rgba (242242247,1.00) |
systemFillColor | # 78788033 | Rgba (120120128,0.20) |
secondarySystemGroupedBackgroundColor | #FFFFFFFF | Rgba (255255255,1.00) |
tertiarySystemGroupedBackgroundColor | #F2F2F7FF | Rgba (242242247,1.00) |
systemFillColor | # 78788033 | Rgba (120120128,0.20) |
secondarySystemFillColor | # 78788028 | Rgba (120120128,0.16) |
tertiarySystemFillColor | #7676801E | Rgba (118118128,0.12) |
quaternarySystemFillColor | # 74748014 | Rgba (116116128,0.08) |
systemRedColor | #FF3B30FF | Rgba (255,59,48,1.00) |
systemGreenColor | #34C759FF | Rgba (52199,89,1.00) |
systemBlueColor | #007AFFFF | Rgba (0122255,1.00) |
systemOrangeColor | #FF9500FF | Rgba (255149,0,1.00) |
systemYellowColor | #FFCC00FF | Rgba (255204,0,1.00) |
systemPinkColor | #FF2D55FF | Rgba (255,45,85,1.00) |
systemPurpleColor | #AF52DEFF | Rgba (175,82,222,1.00) |
systemTealColor | #5AC8FAFF | Rgba (90200250,1.00) |
systemIndigoColor | #5856D6FF | Rgba (88,86,214,1.00) |
systemGrayColor | #8E8E93FF | Rgba (142142147,1.00) |
systemGray2Color | #AEAEB2FF | Rgba (174174178,1.00) |
From the table above, we have some findings;
• Dynamic colors fall into 3 categories: text colors, used for the most basic information foreground color; Fill color refers to the small area and text to convey information; Large area of background color, these colors are contrast color, auxiliary theme color display, such as tableView background color.
• For text colors, level 4 colors, level 2 to level 4 colors include transparency, but not in the name; SeparatorColor has a clear opaque version of opaqueSeparatorColor;
• Different mode colors of the same color are not opposite values (like labelColor), most colors are fine tones, typically like linkColor. Light color: rgba(0,122,255,255), dark color: rgba(9,132,255,255)
• The color of the systemRedColor series is not affected by the appearance mode.
conclusion
I adapted a version of the 9 Star Browser and the remote keyboard using system dynamic colors, which vaguely felt like something was missing from the previous color scheme, although most of it was similar. Submitted for review at 1 am, lying in bed unable to sleep, feeling unhappy all the time, finally got up, changed all the built-in dynamic colors to custom, and submitted again at 3 am;
# if available (iOS 13.0, *) { let backgroundColor = UIColor { (trainCollection) -> UIColor in if trainCollection.userInterfaceStyle == .light { return UIColor(hex: "#f3f3f3ff")! } else { return UIColor(hex: "#2e2f30ff")! } } tableView.separatorColor = backgroundColor } else { // Fallback on earlier versions tableView.separatorColor = UIColor(hex: "#e3e3e3ff") }
Copy the code
Yes, for most apps, you’ll need to deal with both Dark Mode adaptation and iOS version adaptation; Of course, you could write a category or an extension, simplifying this code to
tableVew.seperatorColor = UIColor(hex: "#e3e3e3ff", darkHex:"#2e2f30ff")
Copy the code
Bottom line: Throw out the dynamic colors built into iOS, they’re useless, and the chart above is just to prove how lame dynamic colors are.
Special remind
• Use Any, Dark imageassets for setting custom backButton ICONS in the navigation bar (probably because of my posture), instead
If #available(iOS 13.0, *) { Don't set the back of the tint setting not let on navBarAppearance = UINavigationBarAppearance () navBarAppearance. SetBackIndicatorImage (backImage. transitionMaskImage: backImage) navBarAppearance.titleTextAttributes = [.font: UIFont.systemFont(ofSize: 16, weight: .regular)] navBarAppearance.shadowImage = UIImage() navBarAppearance.shadowColor = .clear navigationController? . The navigationBar. StandardAppearance = navBarAppearance / / change the color of the text and backimage picture let backgroundColor = UIColor { (trainCollection) -> UIColor in if trainCollection.userInterfaceStyle == .light { return UIColor.black } else { return UIColor.white } } navigationController? .navigationBar.tintColor = backgroundColor }
Copy the code
• How to enable dark mode. For the main App, as long as the user has dark mode enabled, your App is dark mode; However, for dark mode of remote keyboard and financial keyboard like 9 Star Browser, the host App should also enable dark mode adaptation. For example, the remote keyboard does not have dark mode in wechat, but has dark mode in Safari.
• Change appearance mode in Settings or in Xcode? How does the App respond? For viewControllers, we know that iOS 13 provides a listener
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if traitCollection.hasDifferentColorAppearance(comparedTo: PreviousTraitCollection) {// adaptation code}}
Copy the code
But what about dynamic colors? Such as
text.textColor = UIColor.label
Copy the code
Cause: the system triggered updateDisplay
self.view.setNeedDispay()
Copy the code
Trigger. LayoutSubView doesn’t fire, viewDidLoad doesn’t fire.
• Use dark mode with caution, especially if you are using apps that use third-party UI components. They have not been upgraded, and you will encounter strange interfaces when adapting.
• The table above is automatically generated, if you want to add new color values or change the format, you can change it by clicking ColorForDarkMode[3]
reference
[1]https://juejin.cn/post/6844903859739967495; [2]https://www.uisdc.com/ios-13-design [3]https://github.com/hite/ColorForDarkMode [4]https://noahgilmore.com/blog/dark-mode-uicolor-compatibility/
5 interesting iOS libraries
IOS gets an arbitrary thread call stack
Face key points are detected in GPUImage
Fully and deeply parse the URL encoding and decoding process on the iOS terminal