Change theme
Presentation (Building the UI)
Summary
This lesson focuses on setting up the global theme of the Flutter application to prevent repetitive, hardcoded styling across the presentation layer. By analyzing the UI design and configuring the default ThemeData to match the predominant dark mode palette, widgets like text automatically adapt to the correct contrasting color. The instructor demonstrates implementing global theme overrides in the application root and explains the mechanics of centering text inside a stretched column on the splash screen.
Key Ideas
Textwidgets inherit default typography and colors from the application's globalThemeData.- Hardcoding colors (e.g.,
color: Colors.white) on individual text components is a poor practice that breaks dynamic theming and adds boilerplate. ThemeData.dark()configures the application to default to a dark color palette, natively converting default text elements to white.copyWith()allows overriding specific properties of a predefined base theme, such as changing thescaffoldBackgroundColorto a custom variable.CrossAxisAlignment.stretchon aColumnforces its children to expand and occupy the full available width of the screen.TextAlign.centercenters text within its own bounding box, which is required when the text widget itself has been stretched to full width by its parent layout.SizedBoxprovides fixed dimensional spacing (e.g.,height: 4) between widgets inside a column or row.
Code Snippets
class Bookly extends StatelessWidget {
const Bookly({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: kPrimaryColor,
),
home: const SplashView(),
);
}
}class SplashViewBody extends StatelessWidget {
const SplashViewBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Image.asset(AssetsData.logo),
const SizedBox(
height: 4,
),
const Text(
'Read Free Books',
textAlign: TextAlign.center,
),
],
);
}
}Architecture Insight
Theming is a cross-cutting concern: the Domain and Data layers must never know about Brightness.dark. By centralizing ThemeData at the app shell (MaterialApp.theme), you keep the layers below it color-blind.
If a use case ever needs to read a theme value, that's a layer leak — the use case shouldn't care about pixels.
Looking ahead — Light/dark switching, when it lands, should ride on the same DI/state layer you'll set up later — a ThemeCubit in presentation, no domain dependency.
My Notes
- Gotcha on Layout Alignment: The instructor addresses a very common Flutter layout confusion. Because the parent
ColumnhascrossAxisAlignment: CrossAxisAlignment.stretch, theTextwidget takes up the entire width of the screen. Therefore, wrapping the text in aCenterwidget wouldn't do anything because the text box itself is already full-width. You *must* use thetextAlign: TextAlign.centerproperty to align the characters within that stretched bounding box. - Theming Strategy: Always audit your design files (Figma/Adobe XD) before writing layout code. Identifying that the app is predominantly dark allows you to set
ThemeData.dark()immediately. This lets Flutter handle the contrast calculations natively, keeping your widget trees clean. [Editor's note]Using a raw integer like4for aSizedBoxheight is fine for drafting, but in a strict Clean Architecture setup, spacing tokens should be extracted to a core design system file (e.g.,AppSpacing.sm) to ensure uniformity.