1. Background In iOS 13 and Android 10, dark mode is introduced.
Reference: https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/dark-mode/ https://developer.android.com/guide/topics/ui/look-and-feel/darktheme 2. Theme value and notificationa. weex.config.env(WXEnvironment) Now contains key theme indicating the theme value of system. - Value dark for dark mode. - Value light for light mode. - Other values not supported yet. - No such key means light mode by default. When system theme changed, value of weex.config.env["theme"] is changed, too. b. Notification when theme changed. When theme changed, a JS event would be fired to root component of each Weex page, just like viewappear and viewdisappear. The event name for theme change is themechanged with theme value as parameter. Objective-C code for theme change event would be: [[WXSDKManager bridgeMgr] fireEvent:instanceId ref:WX_SDK_ROOT_REF type:@"themechanged" params:@{@"theme": @"dark"} domChanges:nil]; 3. Automatical theme management A Weex page developer can use theme value from global configuration and notification to load and reload page with corresponding theme style values. Also Weex supports automatical theme management so that developer do not need to reload the page. a. Using attribute 'invertForDarkTheme' By default, Weex does nothing to components when theme changed. If any component has attribute invertForDarkTheme=true the color values of the following styles would be inverted in dark theme. backgroundColor borderColor color - This attribute is inheritable so you could add this attribute with true value to root component, so that auto-invert of color properties will take effect for all components of a page. - Explicitly set invertForDarkTheme=false will prevent self and subcomponents from auto-inverting colors. But not affecting parents. So you can enable inverting for whole page and disable for a specific component. - Remember that invertForDarkTheme is *false* by default but *inheritable* from parents. b. Using prefixed styles For the following styles(src is an attribute of image component), if prefixed with theme name in format 'xx-theme-xxxx', the style with theme name will be used in a specific theme. backgroundColor borderColor color src For example, a component declares such styles. 'background-color': black;'dark-theme-background-color': white; Black color would be used in light theme and white color be used in dark theme. An image component declares 'src': "http://cdn.taobao.net/SomeImageUsedInLightTheme.jpg";'dark-theme-src': "http://cdn.taobao.net/SomeImageUsedInDarkTheme.jpg"; When theme changes from light to dark, the image of this image component will be automatically reloaded. *Note: Prefixed style has **higher** priority than color inverting. * c. Animations For animations such as keyframe animations and transitions, the invert rule and prefix rule also both apply. transition Currently, Weex only supports 'background-color' to be transitional animated. Consider that currently platform is in dark theme. - Setting new value for dark-theme-background-color, the value will be used for animation. - If component already has dark-theme-background-color explicitly defined, updating style with background-color also takes effect and the color is used directly without inverting. After the animation, the color value will be stored in dark-theme-background-color property, not in background-color property. - If component is in invert mode. Updating background-color, the value will be inverted. keyframe animation The same as transition. For example. - If inverting is enabled and no dark-theme-background-color explicitly defined. The following animation will invert color '#FF0000' and apply to the animation. animation.transition(ref1, { styles: { backgroundColor: '#FF0000', transform: 'translate(250px, 100px)', }, duration: 800, //ms timingFunction: 'ease', needLayout:false, delay: 0 //ms }, function () { modal.toast({ message: 'animation finished.' }) }) - If in animation call dark-theme-background-color is explicitly defined, it will always be used in dark mode and not inverted. animation.transition(ref1, { styles: { darkThemeBackgroundColor: '#0000FF', // Will always be used in dark mode. transform: 'translate(250px, 100px)', }, duration: 800, //ms timingFunction: 'ease', needLayout:false, delay: 0 //ms }, function () { modal.toast({ message: 'animation finished.' }) })
