Resources & Styling

Android Development Fundamentals
Course 1 ยท Chapter 8 ยท Resources & Styling

๐ŸŽจ Resources & Styling

Earlier chapters used string, color, and dimension resources in passing; this final chapter of Course 1 goes deeper โ€” themes, the style/theme distinction, and dark mode, which turns out to be less about writing conditional code and more about how Android's resource system already works.

๐Ÿ“‹ Resources, Revisited

// res/values/strings.xml <resources> <string name="app_name">My First App</string> <plurals name="item_count"> <item quantity="one">%d item</item> <item quantity="other">%d items</item> </plurals> </resources> // res/values/colors.xml <resources> <color name="brand_primary">#3DDC84</color> <color name="text_dark">#1A1A1A</color> </resources> // res/values/dimens.xml <resources> <dimen name="spacing_medium">16dp</dimen> <dimen name="text_size_body">16sp</dimen> </resources>

<plurals> is worth calling out specifically โ€” Android handles pluralization rules per-language automatically (some languages have more than two plural forms), which a hand-rolled if (count == 1) "item" else "items" in Kotlin can't do correctly across languages. dp (density-independent pixels) scales consistently across different screen densities; sp (scale-independent pixels) additionally respects the user's font-size accessibility setting โ€” text sizes should use sp, everything else (padding, margins, icon sizes) should use dp.

๐ŸŽญ Styles vs Themes

A style is a named bundle of attributes applied to one View; a theme is a style applied to an entire Activity or app, cascading down to every View inside it:

// res/values/styles.xml โ€” a STYLE, for one specific kind of View <style name="PrimaryButton"> <item name="android:backgroundTint">@color/brand_primary</item> <item name="android:textColor">@color/text_dark</item> </style>
<Button style="@style/PrimaryButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Submit" />
// res/values/themes.xml โ€” a THEME, applied app-wide via AndroidManifest.xml <style name="Theme.MyFirstApp" parent="Theme.MaterialComponents.DayNight"> <item name="colorPrimary">@color/brand_primary</item> <item name="colorOnPrimary">@color/text_dark</item> </style>

The theme is referenced once, in AndroidManifest.xml's <application android:theme="@style/Theme.MyFirstApp"> โ€” every screen and every View in the app then inherits colorPrimary and friends automatically, which is why Material components (buttons, switches, etc.) already look "on brand" without individually styling each one.

Style/Theme vs CSS

CSS ConceptAndroid Equivalent
A CSS class applied to one elementAn Android style applied to one View
CSS custom properties (--primary-color) set on :rootTheme attributes (colorPrimary) inherited app-wide
Cascading inheritance down the DOM treeTheme attributes cascading down the View tree

๐ŸŒ— Dark Mode โ€” Automatic, Not Conditional

Dark mode isn't implemented with an if (isDarkMode) check scattered through code โ€” it's a resource qualifier. A folder named values-night holds alternate resource definitions that Android automatically swaps in when the system is in dark mode:

res/ โ”œโ”€โ”€ values/ โ”‚ โ””โ”€โ”€ colors.xml # light mode โ€” the default โ”‚ # #FFFFFF โ”‚ # #1A1A1A โ””โ”€โ”€ values-night/ โ””โ”€โ”€ colors.xml # dark mode โ€” same NAMES, different VALUES # #121212 # #E6E6E6

Both files define a color named background โ€” code and layouts reference @color/background exactly once, and Android resolves it to whichever file matches the current system setting, entirely automatically. This requires the app's theme to have a DayNight parent (like Theme.MaterialComponents.DayNight, used above) โ€” a non-DayNight parent theme won't participate in this automatic switching at all.

โš  values-night Is One of Many Qualifiers

The same "same resource name, different folder = different value per condition" idea extends to screen orientation (layout-land/), language (values-fr/, used for the translated-strings example back in Chapter 1), API level (values-v24/), and more โ€” values-night is just the dark-mode instance of a much more general Android mechanism, conceptually parallel to a CSS media query, but resolved once by the OS rather than continuously re-evaluated by the browser.

Don't Hardcode Colors in Layouts

A hardcoded android:textColor="#1A1A1A" directly in a layout XML file bypasses the whole day/night mechanism โ€” it stays that exact color regardless of theme. Always reference @color/..., never a raw hex value, to get automatic dark mode support for free.

Testing Dark Mode

The emulator's system settings (or the notification shade's quick-settings toggle) can switch dark mode on the fly โ€” the running app updates its colors immediately without a restart, which is the fastest way to verify a values-night setup actually works.

๐Ÿ’ป Coding Challenges

Challenge 1: A Reusable Button Style

Define a style named SecondaryButton in styles.xml with a distinct background tint and text color (referencing color resources, not hardcoded hex values), and apply it to two different Buttons in a layout to confirm both pick up the shared styling.

Goal: Practice defining and reusing a style across multiple Views.

โ†’ Solution

Challenge 2: A Custom App Theme

Define a theme in themes.xml with a DayNight parent, setting colorPrimary and colorOnPrimary to two color resources of your choice, and apply it via AndroidManifest.xml. Confirm (by running the app) that a default Material Button now picks up colorPrimary without being individually styled.

Goal: Practice the app-wide theme mechanism, distinct from Challenge 1's per-View style.

โ†’ Solution

Challenge 3: Dark Mode Colors

Create a values-night/colors.xml alongside your existing values/colors.xml, redefining background and text_primary (or similar names) with appropriately inverted values for dark mode. Reference both from a layout via @color/, run the app, and toggle system dark mode to confirm the colors switch automatically with no code changes.

Goal: Practice the values-night qualifier folder pattern end to end.

โ†’ Solution

๐Ÿ’ก Course 1 Complete โ€” What This Sets Up

Android Development Fundamentals closes here having covered the full traditional-View toolkit: setup and tooling, the Activity lifecycle, XML layouts, user interaction and Intents, RecyclerView, Fragments, Navigation Component, and now resources/theming. Course 2 (Architecture & Data) shifts to Jetpack Compose, ViewModels, Room, and networking โ€” building on this foundation rather than replacing it, since Compose still runs inside Activities with the same lifecycle from Chapter 2.

๐ŸŽฏ What's Next

Android Development Fundamentals (Course 1) is complete. Course 2 (Architecture & Data) begins with Jetpack Compose Intro โ€” composables, recomposition, state, and an XML-vs-Compose comparison.