Implementing Dark Mode for iOS 13

Sulta
7 min readNov 5, 2019

--

Dark Mode

In this article, we will learn how to implement dark mode in your App in iOS 13 and later.

In Dark Mode, the system uses a darker color palette for all screens, views, menus, and controls, and it uses more vibrancy to make foreground content stand out against the darker backgrounds.

It’s easy to implement dark mode in your Apps and I’ll demonstrate that to you with some pretty demos through the Article.

Lets Start…

1- Updating colors

The challenge here is how to ensure sufficient color contrast in all appearances, how to achieve a high contrast ratio between your foreground and background content. You should test your content with Increase Contrast and Reduce Transparency turned on. And What if you use hard-coded colors.

in the past, each UI color had only one single value. It was always the same. Now they can be dynamic. The color can have a different value in Light Mode and in Dark Mode.

color is dynamic
  • Semantic colors:
    These are system-defined colors that have a name that explains what they signify (label color, system background color, etc…). You don’t have to think about what mode you’re in and you don’t have to do any work when the mode changes.

System Background Colors

You can see here all levels of the system background colors as you have multiple levels of views in your view controllers.

System Grouped and system backgrounds

Note, Base and Elevated will be used in the dark mode but the difference when we use them. The base is the default in your background but when you present another view controller in the new modal presentation style in ios13 the presented appears above the base this will use the Elevated colors for more contrast.

And this is how can we use them in UIViewcontroller and UITableViewContoller.

How to use system backgrounds in your UIViewController
How to use system backgrounds in your UITableViewController

Note that dark mode is not just a simple inversion of light mode.
It’s more subtle than that.

Label Colors

Apple supports levels of text colors and they let you emphasize which elements are important relative to others.

system label sematic colors

Now, you can find them in color attribute inspector and start using them for :

Fill Colors & Separator colors

The new system palette includes filling colors and separator colors. All of the fill colors and one of the separator colors are semi-transparent, which helps them to contrast well against variable background colors

Filled colors
separator colors

Tint Colors

New dynamic tint color in ios 13

These tint colors are dynamic, meaning that they have variants for Light and Dark Modes. Each tint color has high-contrast variants.

To get you started, you can check out the full-color palette in the Apple Design Resources and the Human Interface Guidelines

Now, if you opt to pick your own custom tint color, try to select colors that work well in both modes. A color that works well in Light Mode, though, might have insufficient contrast in Dark Mode, and vice versa. it’s always best to check your colors with an online color contrast calculator.

if you still need to customize your own color just know that any color can be dynamic.

Let’s see how can we make our own dynamic color!!

how colors can be resolved against light and dark modes

Custom dynamic colors:

The First choice to use the color library in the Assets.xcassets folder, which was introduced with iOS 11. If you make use of this, you must set the minimum deployment target to iOS 11 or higher or create a fallback for lower OS versions.
In the Assets.xcassets folder, select the color that should enable dark appearance.

But what if you are using hard-coded colors!!. in this case you need to do some refactoring here, in the best scenario, assuming that you have an extension for the UIColor and you defined all your custom colors in this extension to be in one place.

Second choice: is to update your customButtonColor() method to resolve color using traitCollection! instead of hard-coded color creation.

resolve hard-coded method to be dynamic

Note, Trait Collection is The iOS interface environment for your app, Use this trait to determine whether your interface should be configured with a dark or light appearance. The default value of this trait is set to the corresponding appearance setting on the user’s device.

Then create a new viewController to test with one UIButton that will use the new customButtonColor to set the button background now the method can resolve the dynamic color.

Now, use the environment override to test your new color.

Test Dark Mode Colors

change button background with your custom dynamic colors

Here You may have noticed that if you need to change the button title text also not just the button background and the text color in each mode you can make some extra changes to let this work.

It is better idea to override the viewDidLayoutSubviews().

Dynamic Controls

UIKit supported controls

If you use UIKit controls, you get the benefits of all of this for free.If you spent time recreating what UIKit gives you for free, with custom controls. Recreating what UIKit gives you for free takes a lot of effort and time, it’s hard to do right, and there’s very little upside for you.

But of course, custom controls are often necessary. UIKit does not provide everything that you need.For example, UIKit doesn’t provide a rating indicator as example but you still can make use of dynamic colors to build your custom control.

Custom Dynamic Controls

customize the rating indicator using dynamic colors

Dynamic Images

Some assets may need a dark appearance to be visible in Dark Mode. Adding a darker image is almost the same as colors. Select the image and set the appearance to ‘Any, Dark’ in the attributes inspector or you can do it by code

create a dynamic image in assets and how can UIimageView dynamically resolve it

If you need the image any time you can resolve it without using UIImageView

Resolve dynamic Image

let image = UIImage(named: "HeaderImage")
let asset = image?.imageAsset
let resolvedImage = asset?.image(with: traitCollection)
// ask the assets to resolve the image with the current traitCollection

Icons & SF Symbols

Using your own icons and SF symbols that consist of one color? Set a tint color to those icons, so you don’t need to add two icons to your app package. Don’t forget that your image should be rendered as a template to support tint colors

Track Dark Mode usage

If you need more customization you should know when the user changes the mode from Light to dark or vise verse.

In fact, when the mode changes, UIKit knows that you override the draw method.
So, it will automatically call setNeedsDisplay() on your view and will draw again with new colors.

UIKit also sets the current Trait Collection for you before it calls several other methods.

UIKit also sets the current Trait Collection during layout.
So, override layout subviews in your view subclass and then add code that resolves dynamic colors.

methods that get called after mode changes

traitCollectionDidChange(_:)

The system calls this method when the iOS interface environment changes. Implement this method in view controllers and views, according to your app’s needs, to respond to such changes.

For example, you might adjust the layout of the subviews of a view controller when an iPhone is rotated from portrait to landscape orientation. The default implementation of this method is empty.

Do custom implementation when user interface style changes.

Disable Dark Mode

You can disable dark mode for a specific view or viewController by overriding Interface style in the current traitCollection.

Overriding User Interface Style

However, you should know that will affect all the trait hierarchy so the subviews of the UIView or UIViewcontroller Childs and its views will automatically get the new overridden user-interface style.

Trait Heirarchy

For the entire app, just set Info.plist key UIUserInterfaceStyle to Light or Dark

Trait Collection Debugging in iOS 13

Enable debug logging with launch argument

-UITraitCollectionChangeLoggingEnabled YES

Thanks for reading article.

refrences : WWDC-2019

You can catch me at:

Linkedin: AhmedHamza

FB: engsulta

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Sulta
Sulta

Written by Sulta

iOS Software Engineer at Vodafone International Services

No responses yet

Write a response