API Development

Getting started with Dark Mode in iOS 13

Dark Mode in iOS 13

Now that iOS 13 is here, you will want to add support for Dark Mode in your next release. Considering Dark Mode is enabled by default for any app compiled with iOS 13, it seems easiest to implement this into your app too. And it is pretty easy getting started with Dark Mode in iOS 13 too!

READ MORE: Learn more about RC Release of Titanium SDK 8.2.0 and GA Release of Appcelerator CLI 7.1.1.

Dark Mode in iOS 13

First, you want to make a configuration file for your colors. In this file, you will specify the colors for both Dark and Light mode. This is called Semantic Colors.

This file is called semantic.colors.json and it has to be created in /app/assets directory in your Alloy app, or in the Resources directory in your classic app. Though if you’re still on a classic app, read about easy migration (like really easy) in a previous blog post.

This semantic.colors.json file will be filled with color specifications. First, we’re going to want to change the of our Windows throughout the app. By default, you might’ve chosen #ffffff as your default, but that color on Dark Mode is perhaps not really dark. Instead, we probably want to go with #666666. This is what our semantic.colors.json file would look like now:

{
  "windowBackgroundColor": {
    "dark": "#666666",
    "light": "#ffffff"
  }
}

The name windowBackgroundColor is our own imagination. You can really choose whatever name you want, even whatKindOfWindowColorDoYouWantNow.

Next, you want to reference this color in your Window. You will have to use fetchSemanticColor to get the object you can use.

const color = Ti.UI.fetchSemanticColor("windowBackgroundColor");

You can use the color variable on any color element, and it will automatically switch based on the dark mode on the user’s phone. Now when you create a Window you can specify the color as you wish.

Ti.UI.createWindow({
  backgroundColor: color
});

In Alloy, it is recommended to put your Semantic Colors on the Alloy.CFG global. Like this:

Alloy.CFG.colors = {
  windowBackgroundColor: Ti.UI.fetchSemanticColor("windowBackgroundColor")
};

You can then use the color in any tss file like this:

backgroundColor: Alloy.CFG.colors.windowBackgroundColor

Although, it might be even easier to copy and paste the following snippet into your alloy.js file, and any color you specify in the json file will be automatically loaded.


const colors = require('/semantic.colors.json');

Alloy.CFG.styles = {};
for (var [ color ] of Object.entries(colors)) {
  Alloy.CFG.styles[color] = Ti.UI.fetchSemanticColor(color)
}

Now you can use any color you specify like this:

backgroundColor: Alloy.CFG.styles.windowBackgroundColor

Specifying alpha for colors

Not only can you specify colors, but you can also specify alpha as a property in Semantic Colors. Instead of providing the #hex of a color, you can specify it like this:

"dark": {
  "color": "#666666",
  "alpha": "50.0" // anywhere between 0 and 100
}

Specifying Dark Mode specific images

Now that you know how to create a specification for a Semantic Color you can apply this to any color of any property you like throughout your app. Keep in mind that Dark Mode actually needs to be dark and easy on the eyes. That is the whole purpose of Dark Mode in the first place.

Next, images. Any image you currently have in your app that doesn’t work on light mode can have a Dark Mode version. Luckily this has been made really easy for you. You don’t have to change anything in your code or styling, you only have to add new images.

Say you have icon.png right now. This would mean you probably have the following files:

/app/assets/icon.png
/app/assets/icon@2x.png
/app/assets/icon@3x.png

Now, you only need to add Dark Mode files by adding the -dark suffix to your filenames, and it should look like this:

/app/assets/icon.png
/app/assets/icon-dark.png
/app/assets/icon@2x.png
/app/assets/icon-dark@2x.png
/app/assets/icon@3x.png
/app/assets/icon-dark@3x.png

The -dark files will be automatically picked up.

Detecting Dark Mode

Not only can you specify colors for Dark Mode, but you can also detect which mode it is, and you can detect when the mode changes. This is useful if you want to customize the views more than just colors/images.

const currentStyle = Ti.App.iOS.userInterfaceStyle

The constant above contains which style is currently used, and you can check which one it is by using the built-in constants like this:

if (currentStyle === Ti.App.iOS.USER_INTERFACE_STYLE_LIGHT) {    
  // light mode
} else if (currentStyle === Ti.App.iOS.USER_INTERFACE_STYLE_DARK) {    
  // dark mode
}

Then you want to detect any changes. This is done by listening to the event made for this.

Ti.App.iOS.addEventListener('traitcollectionchange', (e) => {    
  // mode changed
});

After the event has fired mode has changed. In the callback use the Ti.App.iOS.userInterfaceStyle constant again to check which mode is active right now. Keep in mind this event could fire more than once, so it might be wise to track the mode yourself so you don’t rerender when there is no need for it.

Alloy Theming

When using Dark Mode and semantic.colors.json you, of course, want to theme it too using Alloy Themes. Luckily this is really easy since the file is located in the assets directory. Put a semantic.colors.json file inside the /app/themes/[your theme name]/assets/ directory and it will overwrite the one inside app/assets.

Follow guidelines

Apple has specified guidelines for Dark Mode. You can read it at their docs site. Try to follow this guideline as closely as possible. And make your app easy on the eyes of your app users.

Conclusion

It is fairly easy to add Dark Mode to your app, and you should add it. It won’t be long before users expect apps to have it and being ahead of that is always a good impression towards your users.

As always, if there are any questions jump on the TiSlack community and ask in the #helpme channel.