Welcome to my personal website: www.sketchk.xyz

The overview

As one of the new features of iOS 13, Dark Mode brings more possibilities for the presentation of App, but also brings a lot of adaptation work to developers.

There are three things developers need to think about when adapting Dark Mode:

  1. How do I get current status and information? (Light Mode or Dark Mode)
  2. Which design specification does the effect of adaptation follow? (Apple design specification, or custom design specification)
  3. Determine which elements need to be adapted? (Colors, blur effects, design materials, or other elements)

1. Check the current display status

In iOS 13, since the base classes UIView and UIViewController already comply with the UITraitEnvironment protocol, We can judge the current Apparance status of the App through UITraitCollection. The code looks like this:

The Swift code is as follows:

let isDark = UITraitCollection.current.userInterfaceStyle == .dark
let realColor = UIColor.systemBackground.resolvedColor(with: traitCollection)
let realImage = UIImage(named: "Header")? .imageAsset? .image(with: traitCollection)Copy the code

The code for Objective-C looks like this:

BOOL isDark = [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark? YES: NO;
UIColor *realColor = [[UIColor systemBackgroundColor] resolvedColorWithTraitCollection:traitCollection];
UIImage *image = [[[UIImage imageNamed:@"Header"] imageAsset] imageWithConfiguration:traitCollection]
Copy the code

Note that in the code above we call [UITraitCollection currentTraitCollection], but UITraitCollection does not exist as a singleton. Each view and ViewController has its own property of type UITraitCollection.

So we could have gotten this property by traitCollection. Or self. TraitCollection.

Before, however, not all method executions, UIKit will help us do the UITraitCollection. The current Settings for the self. TraitCollection, only in the following method will do this:

UIView UIViewController UIPresentationController
draw()
layoutSubview() viewWillLayoutSubviews()

viewDidLayoutSubviews()
containerViewWillLayoutSubviews()

containerViewDidLayoutSubviews()
traitCollectionDidChange()

tintColorDidChange()
traitCollectionDidChange() traitCollectionDidChange()

2. Which design specification does the effect of adaptation follow?

Before we can actually write the code, we need to have a deeper understanding of the implications behind adapting Dark Mode.

Apple has a number of apis to help developers quickly adapt to Dark Mode, but is this the API you should use? For example, what does it mean for the system to give systemBlue, systemGray, etc apis?

It should be made clear that the systemBlue apis are essentially Dark Mode color matching under Apple’s Human Interface Guidelines, which does not mean that these color matching should be used mindlessly on your App.

Most of Apple’s native apps are based on white or Light colors. Therefore, under this design specification, the API provided by Apple can switch between Light Mode and Dark Mode well, and the visual effect of the App is very amazing.

However, if your App is not light-colored, like The orange color of Taobao, the blue color of Ele. me, or even the dark color of more flash, if they directly use Apple’s design specifications, from the perspective of visual experience, it may seem a little mismatched, and the API provided by Apple to you will be a little redundant.

Therefore, you need to know your own requirements before you start. Do these design specifications provided by Apple conform to the current tone of the App, or the expectations of the designer and you?

If so, feel free to use the apis provided by Apple. The styles represented by these apis can be found in Apple’s Human Interface Guidelines and Resource.

If not, abstract out an intermediate layer or SDK to define these changes based on your own App design specifications.

2.1 Interpretation of API related to design specification

The API associated with Dark Mode has several features

  • And the apis that are adaptable styles or colors can be grouped into three types: Adaptable Styles, light styles, dark styles and Adaptable Styles contain words that are system related and can change colors automatically depending on the system. The light and Dark versions end with themselves and don’t switch colors depending on the system
  • The API of Activity Indicator and Status Bar and Dark Mode feature complement each other to clarify the scope of the API. For example,UIActivityIndicatorViewThe style attribute fromgray , white.whiteLargeTurned out to belargemedium.UIStatusBarThe style attribute fromdefaultlightContentTurned out to bedefaultlightContentdarkContent, includingdefaultStyles display different colors based on the current mode

3. Determine which elements need to be adapted.

The core question here is what elements need to be adapted after the Appearance switch?

Most people’s first instinct is the color of the control, such as the background color of the control and the content color of the control. Are there any other elements?

Obviously, there are two types to consider, one is the picture material, the other is the blur effect, we first briefly elaborate on the necessity of adaptation of these two elements

  • The adaptation of image materials is obviously necessary. For example, ICONS in TAB bar or Navigation bar will become difficult to identify in dark mode after switching to dark mode.

  • If the image material needs to solve the problem of identification, then the fuzzy effect needs to solve the problem of coordination. If the overall blur effect is too white in dark mode, it will appear to be a little incompatible, which will affect the user experience.

With the necessity stated above, let’s talk about adaptation for different elements

3.1 Adaptation of background color types

If the system color is what you expect, you can use the following statement to implement dark mode adaptation

self.view.backgroundColor = .systemBackground
Copy the code

If the system color does not match your expectations, use the following statement to implement dark mode adaptation

self.textView.textColor = .myDynamicColor

extension UIColor {
    class var myDynamicColor: UIColor {
        get{.init(dynamicProvider: { (traitCollection) -> UIColor in
                if traitCollection.userInterfaceStyle == .dark {
                    return UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 1)}else {
                    return UIColor(displayP3Red: 255, green: 255, blue: 255, alpha: 1)}})}}}Copy the code

3.2 Adaptation of fuzzy effect

In general, the components in the App are directly using the UIBlurEffectView component provided by the system. The following code can quickly complete the matching of Dark Mode. Of course, the enumeration value starting with system in the style needs to be selected according to your own situation.

let blurView = UIVisualEffectView(effect: UIBlurEffect.init(style: .systemMaterial))
Copy the code

If you develop your own blur control, then you will need to develop a new API according to the design specifications of your App.

3.3 Adaptation of picture materials

We can use the new Apperance property for the image control in Xcassets to set the images to be used in both modes, such as showing sunset photos in dark mode and sunrise photos in normal mode.

4 summarizes

Congratulations! Now that you’ve mastered the basics of adapting Dark Mode, all you need to do is practice.

If you want to learn more about Dark Mode, you can watch WWDC 2019 Session 214: Implementing Dark Mode on iOS