Add custom image to book details view
Presentation (Building the UI)
Summary
This lesson focuses on reusing an existing image widget for the book details screen and ensuring it scales responsively. The instructor demonstrates how an AspectRatio widget behaves when constrained by screen width, highlighting the difference between fixed and relative padding. By utilizing MediaQuery to apply padding as a percentage of the screen width, the image maintains its visual proportions across various device sizes. Finally, the widget is renamed to reflect its new, generalized role within the presentation layer, breaking its conceptual tie to just the home screen's featured list.
Key Ideas
- Widget reusability reduces code duplication by repurposing existing components across different views.
AspectRatiowidget automatically calculates its height based on the provided width constraint and the specified ratio.- Fixed pixel constraints (like horizontal padding) can break visual proportions when a layout is rendered on varying screen sizes.
MediaQueryprovides the device's screen dimensions, allowing for accurate relative sizing calculations.- Relative padding (e.g., multiplying screen width by a decimal like 0.17) ensures the child widget scales proportionally across all devices.
- Refactoring widget names to be generic (e.g., from
FeaturedListViewItemtoCustomBookImage) is necessary when a component is shared across multiple features.
Code Snippets
class BookDetailsViewBody extends StatelessWidget {
const BookDetailsViewBody({super.key});
@override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
children: [
const CustomBookDetailsAppBar(),
Padding(
padding: EdgeInsets.symmetric(horizontal: width * .17),
child: const CustomBookImage(),
),
],
),
);
}
}class CustomBookImage extends StatelessWidget {
const CustomBookImage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 2.7 / 4,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.red,
image: const DecorationImage(
fit: BoxFit.fill,
image: AssetImage(
AssetsData.testImage,
),
),
),
),
);
}
}My Notes
- The instructor's approach to responsive scaling using
MediaQuery.of(context).size.width * 0.17is a quick and effective way to constrain anAspectRatiowidget dynamically without hardcoding pixel values. - [Editor's note] As of Flutter 3.10+, you should prefer
MediaQuery.sizeOf(context).widthoverMediaQuery.of(context).size.width. The olderof(context)method binds the widget to the *entire* media query context, meaning the widget will needlessly rebuild if *anything* changes (like text scaling, device orientation, or the keyboard appearing).sizeOf(context)exclusively listens to size changes, making it more performant. - The decision to rename the widget from
FeaturedListViewItemtoCustomBookImageis a great modularization habit. Widgets should be named based on *what they are*, not *where they were originally used*, once they are promoted to shared components within the presentation layer.