Read the original article๏ผ๐ HarmonyOS Next: Supporting Light and Dark Color Modes in Your App
Introduction
There are two main types of themes: custom app themes and built-in dark and light themes. Custom app themes can be created by developers, while dark and light themes are integrated into the operating system. In this article, we will focus on built-in dark and light themes.
- ๐โ๏ธ The phone's built-in systems support both Classic Dark Mode and Light Mode.
- ๐จ Custom app skinning theme, which can be defined by a developer.
๐โ๏ธ Dark and Light Mode Implementation
Let's initiate a project to implement both dark ๐ and light ๐ color modes.
Scenarios based on Dark & Light mode settings:
- The color mode of the app is in sync with the system color mode (dark/light) by default.
- We can disable sync between the system color mode and the app manually.
- We can select light or dark mode manually.
- We can use components that have defined colors statically that wonโt be affected by any color mode setting (system/app).
- We can use components that have defined colors dynamically, which will be affected by the user's will.
๐จโ๐ป Implementing All Scenarios of Dark & Light Mode
First, check the app's current colorMode. It returns an integer or undefined: 1 for light mode โ๏ธ and 0 for dark mode ๐.
Important! โ ๏ธ This will set the appโs color mode ๐จ, not the systemโs. By default, they are synced ๐, but if changed manually, they may differ.
Button('Get Settings').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
this.colorMode = context.config.colorMode === 1 ? 'Light' : 'Dark';
})
.width('40%')
To set the color mode, you have two options: Light and Dark mode. Once you manually set the app's color mode, it will remain that way even if the system's color mode changes.
Button('Set Dark').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
this.colorMode = 'Dark';
})
.width('40%')
Button('Set Light').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
this.colorMode = 'Light';
})
.width('40%')
To assign colors that will be used during color mode changes, you need to make the color properties of your components dynamic. Start by defining different colors for each color mode. After creating the project, you will find two files in the entry/src/main/resources folder: one named "Base" and the other named "Dark."
In base/element/color.json you define colors for light color mode, and in dark/element/color.json you define colors for dark color mode.
After defining and setting component colors through the files listed below, they will automatically change according to dark or light mode.
Please ensure that the names are accurate and consistent in both files.
{
"color": [
{
"name": "start_window_background",
"value": "#000000"
},
{
"name": "index_row_background_color",
"value": "#FF393939"
},
{
"name": "index_text_color",
"value": "#FFDBDBDB"
}
]
}
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
},
{
"name": "index_text_color",
"value": "#FF393939"
},
{
"name": "index_row_background_color",
"value": "#FFDBDBDB"
}
]
}
After setting the dark and light colors in color.json during a color mode change, your component's color will be updated according to the theme.
Row() {
Text('This will change since its dynamically set.')
.width('100%')
.textAlign(TextAlign.Center)
.fontColor($r('app.color.index_text_color')) // this is the magic part ๐ช
.padding(10)
}
.width('50%')
.height('20%')
.backgroundColor($r('app.color.index_row_background_color')) // this is the magic part ๐ช
If you want to make it static and unaffected by mode changes, you can choose colors as desired. Here is an example:
Row() {
Text('This won\'t change since its statically set.')
.width('100%')
.textAlign(TextAlign.Center)
.fontColor(Color.Black) // this won't change in any case ๐ซ
.padding(10)
}
.width('50%')
.height('20%')
.backgroundColor(Color.White) // this won't change in any case ๐ซ
๐ขโ๐จ Important Notes
It's essential to specify a color when using a built-in component; otherwise, it will default to the standard theme, even if no colors are defined in the JSON files.
Here, you can view an official document explaining how judgment works. You can find the default theme colors for both dark and light modes here.
๐คIf you want to change the start window background, it is set to default in the base and dark color.json files, named start_window_background. This is implemented in the module.json5 as shown here:
"startWindowBackground": "$color:start_window_background",
If you want to sync with the system color mode, set it like this to revert to the default.
Button('Set Auto').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
this.colorMode = context.config.colorMode === 1 ? 'Light' : 'Dark';
})
.width('40%')
You can access the full code here: ๐๐
import { common, ConfigurationConstant } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
@State colorMode: string = '';
build() {
Row() {
Column({ space: 20 }) {
Text('Color Mode\n' + this.colorMode)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
Row() {
Text('This won\'t change since its statically set.')
.width('100%')
.textAlign(TextAlign.Center)
.fontColor(Color.Black)
.padding(10)
}
.width('50%')
.height('20%')
.backgroundColor(Color.White)
Row() {
Text('This will change since its dynamically set.')
.width('100%')
.textAlign(TextAlign.Center)
.fontColor($r('app.color.index_text_color'))
.padding(10)
}
.width('50%')
.height('20%')
.backgroundColor($r('app.color.index_row_background_color'))
Button('Get Settings').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
this.colorMode = context.config.colorMode === 1 ? 'Light' : 'Dark';
})
.width('40%')
Button('Set Auto').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
this.colorMode = context.config.colorMode === 1 ? 'Light' : 'Dark';
})
.width('40%')
Button('Set Dark').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
this.colorMode = 'Dark';
})
.width('40%')
Button('Set Light').onClick(() => {
let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
this.colorMode = 'Light';
})
.width('40%')
}
.width('100%')
}
.height('100%')
}
}
๐Conclusion
Huawei HarmonyOS, along with ArkTS, simplifies development by making it more modular. ๐ As demonstrated in this example, it automatically manages color mode changes in applications ๐จ while also enabling developers to customize UI components as they wish. This approach to handling color modes allows for easier management of design elements. โจ
Top comments (0)