Best seller item done
Presentation (Building the UI)
Summary
In this lesson, the instructor completes the UI for the "Best Seller" list item by building the rating component. The primary focus is on constructing the BookRating widget using a Row to align a star icon and text elements. A significant portion of the lesson covers layout constraints, specifically how to use the Expanded widget to force a parent Column to take up all available horizontal space so that a Spacer inside a child Row functions correctly. Finally, the instructor demonstrates good structural practices by extracting the BookRating widget into its own dedicated file to keep the code organized and maintainable.
Key Ideas
BookRatingwidget encapsulates the star icon, rating score, and rating count within aRow.FontAwesomeIcons.solidStaris preferred over the default Material star icon for a sharper visual appearance.Spacerwidget is used within aRowto push the price and rating apart, but it requires the parent to have a bounded or expanded width to function.Expandedwidget must wrap the parentColumnto grant it the maximum available width, which in turn allows the childRowto expand properly.TextStyle.copyWith()allows for quick inline overrides of predefined styles, such as changing the color or font weight, without creating a new style from scratch.- Extracting smaller components like
BookRatinginto separate files prevents a single UI file from becoming bloated and hard to read.
Code Snippets
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../../../core/utils/styles.dart';
class BookRating extends StatelessWidget {
const BookRating({super.key});
@override
Widget build(BuildContext context) {
return Row(
children: [
const Icon(
FontAwesomeIcons.solidStar,
color: Color(0xffFFDD4F),
),
const SizedBox(
width: 6.3,
),
const Text(
'4.8',
style: Styles.textStyle16,
),
const SizedBox(
width: 5,
),
Text(
'(245)',
style: Styles.textStyle14.copyWith(
color: const Color(0xff707070),
),
),
],
);
}
}Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ... title and author text widgets
Row(
children: [
Text(
'19.99 €',
style: Styles.textStyle20.copyWith(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const BookRating(),
],
),
],
),
),My Notes
The main gotcha in this lesson is the nested Row -> Column -> Row layout issue. The instructor correctly demonstrates that a nested Row won't automatically expand to fill horizontal space if its parent Column doesn't do so first.
- Spacer vs MainAxisAlignment: The instructor uses a
Spacer()to push the price to the left and the rating to the right.[Editor's note]An equally valid and slightly cleaner approach is to usemainAxisAlignment: MainAxisAlignment.spaceBetweenon theRowitself, which eliminates the need for the extraSpacerwidget. - Mock Data: The ratings (4.8) and counts (245) are hardcoded for now.
[Editor's note]In a real Clean Architecture setup, these values will eventually be passed down from the domain entity via the constructor ofBookRating.