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