Search result view ui done
Presentation (Building the UI)
Summary
Construct the UI for the search feature by composing a custom text field and a scrollable results list. Extract the text field into a dedicated CustomSearchTextField widget with tailored input decorations, including outline borders and a magnifying glass suffix icon controlled by an Opacity widget. Reuse previously built list view items to display search results, ensuring the list is wrapped in an Expanded widget to properly occupy the available vertical space while maintaining scrollability independent of the parent layout.
Key Ideas
- Modularizing form inputs by extracting a customized
TextFieldinto a standaloneStatelessWidgetfor better maintainability. - Customizing
InputDecorationusingOutlineInputBorderto explicitly define bothenabledBorderandfocusedBorderstates. - Utilizing the
Opacitywidget to soften the visual presence of UI elements like the suffix icon without altering the core color palette. - Reusing existing UI components (like
BookListViewItem) within new contexts (SearchResultListView) to maintain design consistency and reduce code duplication. - Managing layout constraints in
Columnlayouts by wrapping scrollable children (ListView) inExpandedwidgets to prevent infinite height errors. - Adjusting
ScrollPhysicscontextually: removingNeverScrollableScrollPhysicswhen aListViewbecomes the primary scrolling area rather than being embedded inside a broader custom scroll view.
Code Snippets
class CustomSearchTextField extends StatelessWidget {
const CustomSearchTextField({super.key});
@override
Widget build(BuildContext context) {
return TextField(
decoration: InputDecoration(
enabledBorder: buildOutlineInputBorder(),
focusedBorder: buildOutlineInputBorder(),
hintText: 'Search',
suffixIcon: IconButton(
onPressed: () {},
icon: const Opacity(
opacity: .8,
child: Icon(
FontAwesomeIcons.magnifyingGlass,
size: 22,
),
),
),
),
);
}
OutlineInputBorder buildOutlineInputBorder() {
return OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.white,
),
borderRadius: BorderRadius.circular(12),
);
}
}class SearchResultListView extends StatelessWidget {
const SearchResultListView({super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.zero,
itemCount: 10,
itemBuilder: (context, index) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: BookListViewItem(),
);
},
);
}
}IconButton(
onPressed: () {
GoRouter.of(context).push(AppRouter.kSearchView);
},
icon: const Icon(
FontAwesomeIcons.magnifyingGlass,
size: 22,
),
)Architecture Insight
Search is its own feature module — it gets its own lib/features/search/ tree. The temptation to nest it under home/ because it's accessed from the home screen is wrong: search has its own use cases (debounced query, result ranking, history) that don't apply to home browsing.
A good test for "is this its own feature?": does it have its own domain language? Search has *queries*, *results*, *suggestions*. Home has *featured*, *newest*. Different vocabularies → different features.