Create custom app bar
Presentation (Building the UI)
Summary
This lesson focuses on building the custom app bar for the home screen by breaking the UI into smaller, manageable widgets to keep the presentation layer clean. It demonstrates how to create a CustomAppBar using a Row with a logo image and a search icon separated by a Spacer. A key part of the lesson involves matching the design specifications closely, which leads to replacing the default Material search icon with a more visually accurate FontAwesome alternative and adjusting padding and sizes to align perfectly with the provided Adobe XD mockup.
Key Ideas
HomeViewdelegates its body to a customHomeViewBodywidget to keep the main view file uncluttered.CustomAppBaris extracted into its own stateless widget to maintain modular UI code and avoid deeply nested widget trees.Rowaligns the logo image and search button horizontally across the screen.Spacerwidget dynamically fills the empty space between the logo and the search icon, pushing them to opposite ends of the app bar.IconButtonprovides out-of-the-box touch feedback (splash colors) and padding, making it preferable to wrapping a standardIconin aGestureDetector.- Default Material icons may not always match the design mockup perfectly; third-party packages like
font_awesome_flutterprovide necessary alternatives. FontAwesomeIcons.magnifyingGlassis utilized to match the specific stroke thickness and handle length of the search icon from the design.- Padding is applied symmetrically (horizontal and vertical) to ensure the app bar sits correctly within the screen margins.
Code Snippets
import 'package:bookly/features/home/presentation/views/widgets/home_view_body.dart';
import 'package:flutter/material.dart';
class HomeView extends StatelessWidget {
const HomeView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: HomeViewBody(),
);
}
}import 'package:bookly/features/home/presentation/views/widgets/custom_app_bar.dart';
import 'package:flutter/material.dart';
class HomeViewBody extends StatelessWidget {
const HomeViewBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: const [
CustomAppBar(),
],
);
}
}import 'package:bookly/core/utils/assets.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class CustomAppBar extends StatelessWidget {
const CustomAppBar({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 40),
child: Row(
children: [
Image.asset(
AssetsData.logo,
height: 18,
),
const Spacer(),
IconButton(
onPressed: () {},
icon: const Icon(
FontAwesomeIcons.magnifyingGlass,
size: 24,
),
)
],
),
);
}
}Architecture Insight
core/widgets/ is the CA-correct home for components reused across features. The test: if you can imagine two unrelated features rendering this widget, it doesn't belong inside one feature folder.
If only one feature uses it today, keep it local. Don't promote on speculation — premature reuse is harder to undo than late reuse.
My Notes
The instructor heavily emphasizes matching the UI perfectly to the designer's intent. He actively searches for a specific search icon (using FontAwesome's magnifying-glass instead of Material's Icons.search) to match the exact stroke width and handle length from the Adobe XD file.
- `Spacer` vs `MainAxisAlignment`: The instructor uses a
Spacer()widget to push the logo and icon apart. An alternative approach would be omitting theSpacerand addingmainAxisAlignment: MainAxisAlignment.spaceBetweento theRowitself. Both work well, butspaceBetweenavoids adding an extra widget node to the tree. - `[Editor's note]` UI vs Logic priority: The instructor suggests UI errors are worse than logic errors because clients notice them immediately. In the context of Clean Architecture, this is somewhat contradictory. Clean Architecture exists precisely because complex business logic is fragile and hard to maintain over time. While UI is what the client *sees*, deep logic flaws can break the application entirely.