1<?xml version="1.0" encoding="UTF-8"?> 2<!-- 3 Copyright 2013 The Android Open Source Project 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16--> 17 18<sample> 19 <name>DarkTheme</name> 20 <group>UI</group> 21 <package>com.example.android.darktheme</package> 22 23 <minSdk>14</minSdk> 24 <dependency>com.google.android.material:material:1.1.0-alpha06</dependency> 25 <dependency>androidx.appcompat:appcompat:1.1.0-alpha05</dependency> 26 <dependency>androidx.constraintlayout:constraintlayout:2.0.0-beta1</dependency> 27 <dependency>androidx.preference:preference:1.1.0-alpha05</dependency> 28 29 <strings> 30 <intro> 31 <![CDATA[ 32 Sample demonstrating the different ways to support Dark Mode on Android. 33 Uses the Material Design Components Library. 34 ]]> 35 </intro> 36 </strings> 37 38 <template src="base" /> 39 <androidX>true</androidX> 40 41 <metadata> 42 <status>PUBLISHED</status> 43 44 <categories>UI</categories> 45 <technologies>Android</technologies> 46 <languages>Java</languages> 47 <solutions>Mobile</solutions> 48 49 <screenshots> 50 <img>screenshots/light_1_welcome.png</img> 51 <img>screenshots/light_2_preferences.png</img> 52 <img>screenshots/light_3_settings.png</img> 53 <img>screenshots/light_4_theme_options.png</img> 54 <img>screenshots/dark_1_welcome.png</img> 55 <img>screenshots/smart_dark_2_preferences.png</img> 56 <img>screenshots/dark_3_settings.png</img> 57 <img>screenshots/dark_4_theme_options.png</img> 58 </screenshots> 59 60 <description> 61 Sample demonstrating the different ways to support Dark Mode on Android. 62 Uses the Material Design Components Library. 63 </description> 64 65 <intro> 66Android Q has explicit user support for Dark Mode, allowing users to choose 67whether the device theme is dark or not. There are multiple ways you can allow 68Dark Mode in your app: 69 70### Night mode in AppCompat and Material Components 71 72AppCompat has had "night mode" APIs for a number of years now. It allows developers to 73implement dark mode in their apps using the -night resource qualifier. The [Material Design 74Components library][1] builds upon AppCompat and exposes its own DayNight themes. 75 76The DayNight theme in the AndroidX Material Components library provides Dark Theme backwards 77compatibility down to API 14. The theme we use in the app (specified in 78`AndroidManifest.xml#L23`) extends from DayNight (`values/styles.xml#L16`). 79 80Use theme-defined colours when defining colours for your drawables. For example, we use 81`?attr/colorOnBackground` for the generic text color of the app (`values/styles.xml#35`). 82 83When it's not possible to use theme-defined colours, you can use the -night qualifier to 84extract hard-coded values and switch them out when the configuration changes to night mode. 85For example, we use a different primary colour in dark mode. Check `values-night/colors.xml` 86for more details. You can also specify custom drawables creating a drawable-night folder. 87 88Tell AppCompat what mode to use by calling [`AppCompatDelegate.setDefaultNightMode()`][2] or 89`getDelegate().setLocalNightMode()`. It can take different values: 90- MODE_NIGHT_YES. Always use the dark theme. 91- MODE_NIGHT_NO. Always use the light theme (Smart Dark can override it). 92- MODE_NIGHT_FOLLOW_SYSTEM. Follows the current system setting 93- MODE_NIGHT_AUTO_BATTERY. Dark when battery saver is enabled, light otherwise. 94 95In the code sample, you can find the code related to this in the `ThemeHelper` class. 96 97### Smart Dark 98 99Smart Dark is a new feature in Android Q which can automatically theme a light app to 100dark by dynamically re-coloring the app being drawn at runtime. It has no direct developer 101APIs. It is made for apps which do not have explicit Dark Theme support yet. 102 103Smart Dark applies to any theme whose value of `android:isLightTheme=true`. This is set on 104all of the `Theme.*.Light.*` variants, including those from AppCompat. You can opt-in and opt-out at 105both a theme and view level. Opt-in by setting `android:forceDarkAllowed="true"` 106in the view or theme. Alternatively, you can enable/disable it in the code by calling 107`View#setForceDarkAllowed(boolean)`. 108 109This feature is implemented in the `PreferencesFragment`. As you can see in the 110`layout/fragment_preferences.xml` file, all colours are hard-coded to be light-theme suitable. 111To make it use Smart Dark, the parent view sets `android:forceDarkAllowed="true"` 112(you can see it in `layout/fragment_preferences.xml#L19`). In this case, when Smart Dark is 113active, this screen will be automatically themed to be dark-mode friendly. The system will 114change most of the colours to make that happen. 115 116## Dark Mode in the code sample 117 118The user can decide which theme to use within the app. In the Settings screen, the user 119can choose the Light theme, Dark theme, or System Default (when the app is running on 120Android Q+) or Set by Battery Saver (when running on Android P or earlier). When using the 121System Default option, the system decides the theme based on the Platform System Settings 122introduced in Android Q. 123 124These options, that are also listed above, are the settings that Google recommends. 125Also, it recommends that this user choice is stored and applied whenever the user opens 126the app again. In the code sample, the user preference is automatically stored in 127`SharedPreferences` because we use the androidX preference library. Check `SettingsFragment` 128and `preferences.xml` for more information about it. In the `DarkThemeApplication` class, 129we retrieve and apply the user theme preference when the user opens the app. 130 131Notice that the PreferencesFragment will be only in Dark Mode when the Smart Dark is active. 132You can force it by running `adb shell setprop debug.hwui.force_dark true` on your terminal console. 133 134## Hands on 135 136In the sample, we make views Dark-Mode friendly in different ways: 137 138- *Vectors using tints*. `drawable/ic_brightness_2.xml` is Dark-Mode friendly by 139using the `android:tint` attribute. 140 141- *Vectors using hard-coded colours*. `drawable/ic_brightness.xml` is Dark-Mode friendly by 142setting its View tint in `fragment_welcome.xml#L38`. Also, you can set it programmatically 143as we do with the tinted menu icon `R.id.action_more`. 144 145- *Tinted menu icons*. `R.id.action_more` is tinted programmatically in `MainActivity.java#L85`. 146 147- *Different colorPrimary/colorsecondary for light/dark mode*. We define the primary color 148in `values/styles.xml#L21` where we set "colorPrimary" to `@color/primary`. 149`@color/primary` is defined in both `values/colors.xml` and `values-night/colors.xml`. 150 151- *Text color*. Same way as we did before, the text color is defined in `values/styles.xml` 152with the `"android:textColorPrimary"` attribute. 153 154- *Window background*. The window background is set in `values/styles.xml` with the 155`"android:windowBackground"` attribute. The value is set to `@color/background` so if 156Dark Mode is enabled the splash screen is black instead of white. 157 158- *Apply variations to a color using ColorStateList*. Check out `color/color_on_primary_mask.xml`. 159Instead of creating a new color with an alpha in hexadecimal values, we reuse the color and specify 160the alpha with a percentage number. 161 162- *Enable Smart Dark*. The `PreferenceFragment` is not Dark-Mode friendly. It has all colours 163hard-coded to be suitable for light mode. To opt the Fragment in for Smart Dark, we set 164`android:forceDarkAllowed="true"` in the root View of the Fragment. You can find the code 165in `layout/fragment_preferences.xml#19`. 166 167[1]: https://material.io/develop/android/docs/getting-started/ 168[2]: https://developer.android.com/reference/android/support/v7/app/AppCompatDelegate#setdefaultnightmode 169 </intro> 170 </metadata> 171</sample> 172