Kahibaro
Discord Login Register

10.4 Dark Mode Support

Why Dark Mode Matters

Dark mode is a display option where the background of your app uses dark colors, usually black or very dark gray, and the text and icons use light colors. It improves readability in low light, can reduce eye strain, and on some screens it can even save battery.

On Android, dark mode is not just a color choice. It is a system wide appearance preference. When users switch their device to dark theme, they expect all well designed apps to adapt automatically. Supporting dark mode means your app responds to this system preference without the user needing to change a separate setting inside your app.

System Theme and UI Modes

Android exposes the current theme choice through a concept called UI mode. The main modes you care about are light theme and dark theme. When the system theme changes, Android restarts your activities so they can reload resources that match the new mode.

You do not need to manually check the UI mode for every view. Instead, you define alternative color resources for dark mode and let Android pick the correct set based on the current theme. When your activity is recreated after a theme change, the correct resources are loaded automatically.

Using Night Resource Qualifiers

The core mechanism for dark mode support in Android is the night resource qualifier. This lets you provide one set of resources for light mode and another for dark mode. Android chooses between them based on whether the system is in night mode.

You usually start by creating night variants of your color resource files. A common setup is:

In res/values/colors.xml you might define:

<resources>
    <color name="colorBackground">#FFFFFF</color>
    <color name="colorOnBackground">#000000</color>
</resources>

In res/values-night/colors.xml you use darker backgrounds and lighter text:

<resources>
    <color name="colorBackground">#121212</color>
    <color name="colorOnBackground">#FFFFFF</color>
</resources>

When you reference @color/colorBackground in layouts or styles, Android will automatically use the appropriate value depending on whether night mode is active. You can apply the same pattern to other resource types, such as drawables, by creating drawable-night folders that contain alternative versions of icons or backgrounds tailored for dark mode.

Always keep the same resource names in your values and values-night files. The only difference should be their values, not their names.

AppCompat and DayNight Themes

To support dark mode correctly across a wide range of Android versions, you should use a DayNight theme from the Material Components or AppCompat libraries. This is often chosen when you create a new project in Android Studio.

A typical application theme in res/values/themes.xml might look like this:

<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- Light and dark aware theme attributes -->
</style>

The DayNight parent tells the system that your theme can adapt to both light and dark modes. The system then decides which variant to use based on the current UI mode. For devices that support system wide dark theme, this is automatic. For older versions, the support library simulates the behavior as much as possible.

When you use a DayNight theme, attributes like ?attr/colorSurface, ?attr/colorOnSurface, and similar material color attributes will resolve to different concrete colors in light and dark modes. As long as you design your styles and layouts using theme attributes instead of hardcoded colors, your app will adapt with minimal extra work.

Testing Dark Mode in the Emulator

To verify that your app behaves correctly in dark mode, you should test switching between light and dark themes in the emulator or on a real device.

On modern Android versions, you can usually enable dark theme through system settings such as Display > Dark theme. When you toggle this setting, Android may recreate your activities so they can reload resources for the new mode. Watch how backgrounds, text, icons, and status bar content change when you switch modes.

In Android Studio, you can also preview layouts in dark mode using the layout editor. There is an option to change the UI mode of the preview to night. This helps you quickly see if any text becomes unreadable on dark backgrounds or if any images do not fit the theme.

Using Theme Attributes Instead of Hardcoded Colors

One of the most important habits for reliable dark mode support is to avoid using hardcoded color values directly in layouts and code. Instead, reference theme attributes that can resolve to different colors in light and dark modes.

For example, in your styles file you might define:

<style name="Widget.MyApp.PrimaryText">
    <item name="android:textColor">?attr/colorOnBackground</item>
</style>

In your layout, you apply this style to a TextView instead of setting a fixed android:textColor with a hex value.

If you use Material Components, many components already use theme attributes internally. For instance, MaterialButton and MaterialCardView use color attributes like colorPrimary or colorSurface. As long as these attributes have appropriate light and dark values in your theme, the components will adapt automatically.

In code, if you must retrieve colors, prefer resolving color attributes instead of resources with fixed colors. This keeps your logic aligned with the current theme.

Avoid using hardcoded hex colors such as #FFFFFF or #000000 directly in layouts or code. Use color resources and theme attributes so light and dark variants can be applied correctly.

Handling Icons and Images in Dark Mode

Icons and images can easily become invisible or distracting when the background changes from light to dark. To address this, you can use two strategies.

First, for icons that should adapt to the theme, use vector drawables with tint that comes from a theme attribute. For example, an icon that uses ?attr/colorOnBackground will automatically change from dark to light when switching modes. This avoids needing separate icon files for each theme.

Second, when you have images that cannot be safely tinted, such as logos or detailed graphics, consider providing alternative versions for dark backgrounds. You can place these in drawable and drawable-night folders with the same filename. Android will load the correct version based on the current mode.

If you use images with transparent backgrounds, test them in both light and dark themes to ensure edges and contrast look correct. Sometimes a subtle outline or shadow in the dark version can improve visibility.

Forcing and Overriding Dark Mode Behavior

Sometimes you want your app to follow the system theme. In other cases you may want to provide a manual theme switcher inside your app. With an app level control, the user can choose between light, dark, or system default.

Using the support library, you can request a specific mode for your app while staying compatible with older versions. When you change the mode, your activities are recreated and resources reload with the appropriate night or non night variants.

While it is technically possible to force your app to always stay in light or dark mode, even when the system uses a different theme, this is usually not recommended. Users expect apps to respect the system preference unless there is a strong reason not to. If you offer app specific controls, include a "follow system" option so users can keep consistent behavior with their device setting.

Adapting Other UI Elements for Dark Mode

Dark mode affects more than just the main content area. System controlled UI elements such as the status bar, navigation bar, and system bars around your app also need to be considered.

Many of these areas can be controlled through theme attributes or window flags. For example, the status bar text color can change between dark and light in order to stay visible over your chosen status bar background color. Material Components themes often manage these automatically if you use the provided attributes and default configurations.

You should also consider surfaces such as dialogs, sheets, and menus. If you use material dialogs or bottom sheets that follow the app theme, their backgrounds and text colors will adapt automatically. If you create custom dialogs with their own layouts and styles, make sure they use theme attributes and color resources that have night variants. This keeps dialogs readable and visually consistent in both modes.

Testing these UI pieces in both themes is important. Watch for any mismatched colors, like a light dialog appearing over a dark activity, or system bars that do not match the app's chosen background color.

Common Pitfalls and Visual Checks

When adding dark mode support, several issues appear frequently and are easy to miss without careful checking.

One common problem is insufficient contrast. Text that looks fine on a white background might become too dim on a dark gray background. Use clear, sufficiently bright text colors and avoid mid gray tones for important text in dark mode. Similarly, very bright pure white text on a very dark background can feel harsh, so subtle adjustments can improve comfort while maintaining readability.

Another issue is partial theming. If you convert only some screens to use theme attributes while others rely on hardcoded colors, switching to dark mode may leave some screens looking broken or inconsistent. Try to identify all places where colors are defined and convert them to resource based or attribute based references.

Finally, be careful with custom drawn views or canvases. If you draw directly using fixed colors in custom views, these will not change automatically with dark mode. In that case, read colors from resources or attributes inside your custom drawing logic, so they update when the theme changes.

By combining DayNight themes, values-night resources, theme attributes, and careful visual testing, you can provide reliable dark mode support that feels natural and consistent with the rest of the Android ecosystem.

Views: 2

Comments

Please login to add a comment.

Don't have an account? Register now!