Resources & Styling
๐จ Resources & Styling
๐ Resources, Revisited
<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:
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 Concept | Android Equivalent |
|---|---|
| A CSS class applied to one element | An Android style applied to one View |
| CSS custom properties (--primary-color) set on :root | Theme attributes (colorPrimary) inherited app-wide |
| Cascading inheritance down the DOM tree | Theme 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:
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.
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.
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.
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.
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.