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.
Follow us on social