Android - dark theme

1. Introduction

The operating system we have been using for a long time is based on a light theme. This theme mode can be used without any problems during the day or when there is sufficient light, but it will be very dazzling when used at night when the lights are turned off. Therefore, in order to allow users to use it more comfortably in dimly lit environments, many applications will provide a button within the application to switch to night mode with one key. When the user turns on the night mode, the overall tone of the application will be adjusted to a color more suitable for nighttime browsing. However, it is difficult to achieve global unity in this way of spontaneously implementing night mode by applications, that is, some applications may support night mode, while others do not. And the problem of repeated operations is also very troublesome. For example, if I turn on the night mode in one application, I need to turn it on again in another application, and the same repeated operation is required to turn off the night mode. Therefore, many developers have been calling for Android to support the night mode function at the system level.

Finally, in the Android 10.0 system, Google introduced the dark theme feature, making night mode an officially supported feature. Maybe you will be a little confused, this kind of function does not seem to have too much technical difficulty, why did Android not support it until the 10.0 system? That's because it's not enough for the operating system itself to support a dark theme; all apps have to support it, which is never easy. For this reason, I hope that the applications you develop in the future can support the dark theme well according to the requirements of the Android system. Otherwise, when the user turns on the dark theme, only your application still uses the light theme. , it will appear out of place.

In addition to making nighttime use more comfortable for the eyes, a dark theme can also reduce battery consumption, thereby extending the battery life of the phone, which is a very useful feature.

2. Force Dark

It's a way to quickly adapt an app to a dark theme with little to no extra coding. The working principle of Force Dark is that the system analyzes each layer of View under the light theme application, and automatically converts the colors of these Views to colors that are more suitable for the dark theme before they are drawn to the screen. Note that this method can only be used by apps that originally use a light theme. If your app originally uses a dark theme, Force Dark will not work.

Here we try to use the Force Dark conversion on the MaterialTest project as an example. Enabling the Force Dark function requires the android:forceDarkAllowed attribute, but this attribute is only available from API 29, that is, the Android 10.0 system, and the previous system cannot specify this attribute. So we have to do some system-differential programming.

1. Right-click the res directory→New→Directory to create a values-v29 directory, then right-click the values-v29 directory→New→Values ​​resource file to create a styles.xml file. Then write this file, the code is as follows:

<resources>
 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
 <item name="colorPrimary">@color/colorPrimary</item>
 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
 <item name="colorAccent">@color/colorAccent</item>
 <item name="android:forceDarkAllowed">true</item>
 </style>
</resources>

Except for the android:forceDarkAllowed attribute, everything else is copied from the previous styles.xml file. Here, the android:forceDarkAllowed attribute is added to the AppTheme theme and set to true, indicating that now we allow the system to use Force Dark to force the application into a dark theme. In addition, the values-v29 directory is only read by Android 10.0 and above systems, so this is a way to implement system-differential programming.

Force Dark is such a simple and crude conversion method, and its conversion effect is usually not satisfactory. Therefore, here I do not recommend that you use this automated method to implement a dark theme, but you should use a more traditional implementation——

3. Manual implementation

If you want to achieve the best dark theme effect, don't expect any magical magic to be completed with one click. Instead, you should design both light and dark themes for each interface. This may sound complicated, but we still have some handy tricks to make the process easier.

The built-in themes in the AppCompat library happen to be mainly divided into two categories: light themes and dark themes. For example, Theme.AppCompat.Light.NoActionBar currently used in the MaterialTest project is a light theme, and Theme.AppCompat.NoActionBar is a dark theme. Choosing different themes will have completely different effects in terms of the default color of the controls.

And now, we have an option for a DayNight theme. After using this theme, when the user turns on the dark theme in the system settings, the application will automatically use the dark theme, otherwise it will use the light theme.

1. First delete the values-v29 directory and its contents, and then modify the code in values/styles.xml

<resources>
 <!-- Base application theme. -->
 <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
 <!-- Customize your theme here. -->
 <item name="colorPrimary">@color/colorPrimary</item>
 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
 <item name="colorAccent">@color/colorAccent</item>
 </style>
 ...
</resources>

As you can see, here we specify the parent theme of AppTheme as Theme.AppCompat.DayNight.NoActionBar, which is a DayNight theme. Therefore, under normal circumstances, the MaterialTest project will still use the light theme, which is no different from before, but once the user turns on the dark theme in the system settings, the MaterialTest project will automatically use the corresponding dark theme.

2. Effect of DayNight theme

Although the main content in the interface has been automatically switched to the dark theme, you will find that the title bar and floating buttons still maintain the same color as the light theme. This is because the title bar and the floating button use several color values ​​​​that we defined in colors.xml, and the code is as follows:

<resources>
 <color name="colorPrimary">#008577</color>
 <color name="colorPrimaryDark">#00574B</color>
 <color name="colorAccent">#D81B60</color>
</resources>

This way of specifying the color value reference is equivalent to hard-coding the color of the control, and the DayNight theme cannot dynamically convert these colors.

Fortunately, the solution is not complicated, we only need to do some topic-differential programming. Right-click the res directory→New→Directory to create a values-night directory, then right-click the values-night directory→New→Values ​​resource file to create a colors.xml file. Then specify the color value under the dark theme in this file

Although using the theme-differentiated programming method can help you solve almost all adaptation problems, under the DayNight theme, we'd better minimize the hard-coded way to specify the color of the control, but should use more A theme property that automatically switches colors based on the current theme. For example, black text should usually be set off against a white background, whereas white text should usually be set off against a black background, then we can use the theme attribute to specify the color of the background and text. The example is as follows:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="?android:attr/colorBackground">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center"
 android:text="Hello world"
 android:textSize="40sp"
 android:textColor="?android:attr/textColorPrimary" />
</FrameLayout>

These theme attributes will automatically select the most appropriate color value to present to the user according to the current theme mode of the system

In addition, you may have some special requirements, such as executing different code logics under light and dark themes. Android also supports this, you can use the following code to determine whether the current system is a dark theme at any time:

fun isDarkTheme(context: Context): Boolean {
 val flag = context.resources.configuration.uiMode and
 Configuration.UI_MODE_NIGHT_MASK
 return flag == Configuration.UI_MODE_NIGHT_YES
}

Call the isDarkTheme () method to determine whether the current system is a light theme or a dark theme, and then execute different code logics according to the return value.

In addition, since Kotlin cancels the wording of bitwise operators and uses English keywords instead, the and keyword in the above code actually corresponds to the & operator in Java, and the or keyword in Kotlin corresponds to Java The | operator in the xor keyword corresponds to the ^ operator in Java, which is very easy to understand.

Finally paste your own

 

Guess you like

Origin blog.csdn.net/m0_59482482/article/details/130483714