1*d353a188SXin Li 2*d353a188SXin LiAndroid DarkTheme Sample 3*d353a188SXin Li=================================== 4*d353a188SXin Li 5*d353a188SXin LiSample demonstrating the different ways to support Dark Mode on Android. 6*d353a188SXin Li Uses the Material Design Components Library. 7*d353a188SXin Li 8*d353a188SXin LiIntroduction 9*d353a188SXin Li------------ 10*d353a188SXin Li 11*d353a188SXin LiAndroid Q has explicit user support for Dark Mode, allowing users to choose 12*d353a188SXin Liwhether the device theme is dark or not. There are multiple ways you can allow 13*d353a188SXin LiDark Mode in your app: 14*d353a188SXin Li 15*d353a188SXin LiNight mode in AppCompat and Material Components 16*d353a188SXin Li------------ 17*d353a188SXin Li 18*d353a188SXin LiAppCompat has had "night mode" APIs for a number of years now. It allows developers to 19*d353a188SXin Liimplement dark mode in their apps using the -night resource qualifier. The [Material Design 20*d353a188SXin LiComponents library][1] builds upon AppCompat and exposes its own DayNight themes. 21*d353a188SXin Li 22*d353a188SXin LiThe DayNight theme in the AndroidX Material Components library provides Dark Theme backwards 23*d353a188SXin Licompatibility down to API 14. The theme we use in the app (specified in 24*d353a188SXin Li`AndroidManifest.xml#L23`) extends from DayNight (`values/styles.xml#L16`). 25*d353a188SXin Li 26*d353a188SXin LiUse theme-defined colours when defining colours for your drawables. For example, we use 27*d353a188SXin Li`?attr/colorOnBackground` for the generic text color of the app (`values/styles.xml#35`). 28*d353a188SXin Li 29*d353a188SXin LiWhen it's not possible to use theme-defined colours, you can use the -night qualifier to 30*d353a188SXin Liextract hard-coded values and switch them out when the configuration changes to night mode. 31*d353a188SXin LiFor example, we use a different primary colour in dark mode. Check `values-night/colors.xml` 32*d353a188SXin Lifor more details. You can also specify custom drawables creating a drawable-night folder. 33*d353a188SXin Li 34*d353a188SXin LiTell AppCompat what mode to use by calling [`AppCompatDelegate.setDefaultNightMode()`][2] or 35*d353a188SXin Li`getDelegate().setLocalNightMode()`. It can take different values: 36*d353a188SXin Li- MODE_NIGHT_YES. Always use the dark theme. 37*d353a188SXin Li- MODE_NIGHT_NO. Always use the light theme (Smart Dark can override it). 38*d353a188SXin Li- MODE_NIGHT_FOLLOW_SYSTEM. Follows the current system setting 39*d353a188SXin Li- MODE_NIGHT_AUTO_BATTERY. Dark when battery saver is enabled, light otherwise. 40*d353a188SXin Li 41*d353a188SXin LiIn the code sample, you can find the code related to this in the `ThemeHelper` class. 42*d353a188SXin Li 43*d353a188SXin LiSmart Dark 44*d353a188SXin Li------------ 45*d353a188SXin Li 46*d353a188SXin LiSmart Dark is a new feature in Android Q which can automatically theme a light app to 47*d353a188SXin Lidark by dynamically re-coloring the app being drawn at runtime. It has no direct developer 48*d353a188SXin LiAPIs. It is made for apps which do not have explicit Dark Theme support yet. 49*d353a188SXin Li 50*d353a188SXin LiSmart Dark applies to any theme whose value of `android:isLightTheme=true`. This is set on 51*d353a188SXin Liall of the `Theme.*.Light.*` variants, including those from AppCompat. You can opt-in and opt-out at 52*d353a188SXin Liboth a theme and view level. Opt-in by setting `android:forceDarkAllowed="true"` 53*d353a188SXin Liin the view or theme. Alternatively, you can enable/disable it in the code by calling 54*d353a188SXin Li`View#setForceDarkAllowed(boolean)`. 55*d353a188SXin Li 56*d353a188SXin LiThis feature is implemented in the `PreferencesFragment`. As you can see in the 57*d353a188SXin Li`layout/fragment_preferences.xml` file, all colours are hard-coded to be light-theme suitable. 58*d353a188SXin LiTo make it use Smart Dark, the parent view sets `android:forceDarkAllowed="true"` 59*d353a188SXin Li(you can see it in `layout/fragment_preferences.xml#L19`). In this case, when Smart Dark is 60*d353a188SXin Liactive, this screen will be automatically themed to be dark-mode friendly. The system will 61*d353a188SXin Lichange most of the colours to make that happen. 62*d353a188SXin Li 63*d353a188SXin LiDark Mode in the code sample 64*d353a188SXin Li------------ 65*d353a188SXin Li 66*d353a188SXin LiThe user can decide which theme to use within the app. In the Settings screen, the user 67*d353a188SXin Lican choose the Light theme, Dark theme, or System Default (when the app is running on 68*d353a188SXin LiAndroid Q+) or Set by Battery Saver (when running on Android P or earlier). When using the 69*d353a188SXin LiSystem Default option, the system decides the theme based on the Platform System Settings 70*d353a188SXin Liintroduced in Android Q. 71*d353a188SXin Li 72*d353a188SXin LiThese options, that are also listed above, are the settings that Google recommends. 73*d353a188SXin LiAlso, it recommends that this user choice is stored and applied whenever the user opens 74*d353a188SXin Lithe app again. In the code sample, the user preference is automatically stored in 75*d353a188SXin Li`SharedPreferences` because we use the androidX preference library. Check `SettingsFragment` 76*d353a188SXin Liand `preferences.xml` for more information about it. In the `DarkThemeApplication` class, 77*d353a188SXin Liwe retrieve and apply the user theme preference when the user opens the app. 78*d353a188SXin Li 79*d353a188SXin LiNotice that the PreferencesFragment will be only in Dark Mode when the Smart Dark is active. 80*d353a188SXin LiYou can force it by running `adb shell setprop debug.hwui.force_dark true` on your terminal console. 81*d353a188SXin Li 82*d353a188SXin LiHands on 83*d353a188SXin Li------------ 84*d353a188SXin Li 85*d353a188SXin LiIn the sample, we make views Dark-Mode friendly in different ways: 86*d353a188SXin Li 87*d353a188SXin Li- *Vectors using tints*. `drawable/ic_brightness_2.xml` is Dark-Mode friendly by 88*d353a188SXin Liusing the `android:tint` attribute. 89*d353a188SXin Li 90*d353a188SXin Li- *Vectors using hard-coded colours*. `drawable/ic_brightness.xml` is Dark-Mode friendly by 91*d353a188SXin Lisetting its View tint in `fragment_welcome.xml#L38`. Also, you can set it programmatically 92*d353a188SXin Lias we do with the tinted menu icon `R.id.action_more`. 93*d353a188SXin Li 94*d353a188SXin Li- *Tinted menu icons*. `R.id.action_more` is tinted programmatically in `MainActivity.java#L85`. 95*d353a188SXin Li 96*d353a188SXin Li- *Different colorPrimary/colorsecondary for light/dark mode*. We define the primary color 97*d353a188SXin Liin `values/styles.xml#L21` where we set "colorPrimary" to `@color/primary`. 98*d353a188SXin Li`@color/primary` is defined in both `values/colors.xml` and `values-night/colors.xml`. 99*d353a188SXin Li 100*d353a188SXin Li- *Text color*. Same way as we did before, the text color is defined in `values/styles.xml` 101*d353a188SXin Liwith the `"android:textColorPrimary"` attribute. 102*d353a188SXin Li 103*d353a188SXin Li- *Window background*. The window background is set in `values/styles.xml` with the 104*d353a188SXin Li`"android:windowBackground"` attribute. The value is set to `@color/background` so if 105*d353a188SXin LiDark Mode is enabled the splash screen is black instead of white. 106*d353a188SXin Li 107*d353a188SXin Li- *Apply variations to a color using ColorStateList*. Check out `color/color_on_primary_mask.xml`. 108*d353a188SXin LiInstead of creating a new color with an alpha in hexadecimal values, we reuse the color and specify 109*d353a188SXin Lithe alpha with a percentage number. 110*d353a188SXin Li 111*d353a188SXin Li- *Enable Smart Dark*. The `PreferenceFragment` is not Dark-Mode friendly. It has all colours 112*d353a188SXin Lihard-coded to be suitable for light mode. To opt the Fragment in for Smart Dark, we set 113*d353a188SXin Li`android:forceDarkAllowed="true"` in the root View of the Fragment. You can find the code 114*d353a188SXin Liin `layout/fragment_preferences.xml#19`. 115*d353a188SXin Li 116*d353a188SXin Li[1]: https://material.io/develop/android/docs/getting-started/ 117*d353a188SXin Li[2]: https://developer.android.com/reference/android/support/v7/app/AppCompatDelegate#setdefaultnightmode 118*d353a188SXin Li 119*d353a188SXin LiPre-requisites 120*d353a188SXin Li-------------- 121*d353a188SXin Li 122*d353a188SXin Li- Android SDK 29 123*d353a188SXin Li- Android Support Repository 124*d353a188SXin Li 125*d353a188SXin LiScreenshots 126*d353a188SXin Li------------- 127*d353a188SXin Li 128*d353a188SXin Li<img src="screenshots/light_1_welcome.png" height="400" alt="Screenshot"/> <img src="screenshots/light_2_preferences.png" height="400" alt="Screenshot"/> <img src="screenshots/light_3_settings.png" height="400" alt="Screenshot"/> <img src="screenshots/light_4_theme_options.png" height="400" alt="Screenshot"/> <img src="screenshots/dark_1_welcome.png" height="400" alt="Screenshot"/> <img src="screenshots/smart_dark_2_preferences.png" height="400" alt="Screenshot"/> <img src="screenshots/dark_3_settings.png" height="400" alt="Screenshot"/> <img src="screenshots/dark_4_theme_options.png" height="400" alt="Screenshot"/> 129*d353a188SXin Li 130*d353a188SXin LiGetting Started 131*d353a188SXin Li--------------- 132*d353a188SXin Li 133*d353a188SXin LiThis sample uses the Gradle build system. To build this project, use the 134*d353a188SXin Li"gradlew build" command or use "Import Project" in Android Studio. 135*d353a188SXin Li 136*d353a188SXin LiSupport 137*d353a188SXin Li------- 138*d353a188SXin Li 139*d353a188SXin Li- Stack Overflow: http://stackoverflow.com/questions/tagged/android 140*d353a188SXin Li 141*d353a188SXin LiIf you've found an error in this sample, please file an issue: 142*d353a188SXin Lihttps://github.com/googlesamples/android-DarkTheme 143*d353a188SXin Li 144*d353a188SXin LiPatches are encouraged, and may be submitted by forking this project and 145*d353a188SXin Lisubmitting a pull request through GitHub. Please see CONTRIBUTING.md for more details. 146*d353a188SXin Li 147*d353a188SXin LiLicense 148*d353a188SXin Li------- 149*d353a188SXin Li 150*d353a188SXin LiCopyright 2019 The Android Open Source Project, Inc. 151*d353a188SXin Li 152*d353a188SXin LiLicensed to the Apache Software Foundation (ASF) under one or more contributor 153*d353a188SXin Lilicense agreements. See the NOTICE file distributed with this work for 154*d353a188SXin Liadditional information regarding copyright ownership. The ASF licenses this 155*d353a188SXin Lifile to you under the Apache License, Version 2.0 (the "License"); you may not 156*d353a188SXin Liuse this file except in compliance with the License. You may obtain a copy of 157*d353a188SXin Lithe License at 158*d353a188SXin Li 159*d353a188SXin Lihttps://www.apache.org/licenses/LICENSE-2.0 160*d353a188SXin Li 161*d353a188SXin LiUnless required by applicable law or agreed to in writing, software 162*d353a188SXin Lidistributed under the License is distributed on an "AS IS" BASIS, WITHOUT 163*d353a188SXin LiWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 164*d353a188SXin LiLicense for the specific language governing permissions and limitations under 165*d353a188SXin Lithe License. 166