Building Search UIs with Flutter Searchbox 4.0
Introduction
Search functionality is a vital component of modern applications, significantly enhancing user experience by providing quick access to relevant information. As Flutter continues to gain popularity for building cross-platform apps, integrating a robust search interface has become increasingly important. Enter Flutter Searchbox 4.0, a package that offers a declarative API to seamlessly connect your Flutter app with Elasticsearch or OpenSearch, enabling the creation of powerful search UIs.
In this post, we’ll guide you through setting up a basic search interface using Flutter Searchbox 4.0, highlighting its key features and providing a practical example.
Understanding Flutter Searchbox 4.0
Flutter Searchbox is designed to integrate seamlessly with ReactiveSearch, making it easier to query Elasticsearch and OpenSearch. It allows developers to build responsive and dynamic search UIs with minimal code, leveraging pre-built widgets for autosuggestions, results rendering, facets and maps.
Installation
Before diving into coding, let’s set up the necessary dependencies.
Depend on it
Add the following dependencies to yourpubspec.yaml
file:codedependencies: flutter_searchbox: ^4.0.0 searchbase: ^4.0.0
Install it
Run the following command to install the packages:flutter pub get
Basic Usage
Now that we have the dependencies installed, let’s build a simple search UI.
A Simple Example
The following example demonstrates how to create a search interface with an autosuggestion search widget and a custom result widget.
import 'package:flutter/material.dart';
import 'package:searchbase/searchbase.dart';
import 'package:flutter_searchbox/flutter_searchbox.dart';
void main() {
runApp(FlutterSearchBoxApp());
}
class FlutterSearchBoxApp extends StatelessWidget {
final searchbaseInstance = SearchBase(
'good-books-ds',
'https://appbase-demo-ansible-abxiydt-arc.searchbase.io',
'a03a1cb71321:75b6603d-9456-4a5a-af6b-a487b309eb61',
appbaseConfig: AppbaseSettings(
recordAnalytics: true,
userId: 'test@dev',
),
);
@override
Widget build(BuildContext context) {
return SearchBaseProvider(
searchbase: searchbaseInstance,
child: MaterialApp(
title: "SearchBox Demo",
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SearchBox Demo'),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () {
showSearch(
context: context,
delegate: SearchBox(
id: 'search-widget',
enableRecentSearches: true,
enablePopularSuggestions: true,
showAutoFill: true,
maxPopularSuggestions: 3,
size: 10,
dataField: [
{'field': 'original_title', 'weight': 1},
{'field': 'original_title.search', 'weight': 3},
],
),
);
},
),
],
),
body: Center(
child: SearchWidgetConnector(
id: 'result-widget',
dataField: 'original_title',
react: {
'and': ['search-widget'],
},
size: 10,
triggerQueryOnInit: true,
preserveResults: true,
builder: (context, searchController) => ResultsWidget(searchController),
),
),
);
}
}
class ResultsWidget extends StatelessWidget {
final SearchController searchController;
ResultsWidget(this.searchController);
@override
Widget build(BuildContext context) {
return Column(
children: [
Card(
child: Align(
alignment: Alignment.centerLeft,
child: Container(
color: Colors.white,
height: 20,
child: Text(
'${searchController.results.numberOfResults} results found in ${searchController.results.time.toString()} ms',
),
),
),
),
Expanded(
child: ListView.builder(
itemCount: searchController.results.data.length + 1,
itemBuilder: (context, index) {
WidgetsBinding.instance.addPostFrameCallback((_) {
var offset = (searchController.from ?? 0) + searchController.size;
if (index == offset - 1 && searchController.results.numberOfResults > offset) {
searchController.setFrom(offset, options: Options(triggerDefaultQuery: true));
}
});
return index < searchController.results.data.length
? Container(
margin: const EdgeInsets.all(0.5),
padding: const EdgeInsets.fromLTRB(0, 15, 0, 0),
decoration: BoxDecoration(border: Border.all(color: Colors.black26)),
height: 200,
child: Row(
children: [
Expanded(
flex: 3,
child: Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Image.network(
searchController.results.data[index]["image_medium"],
fit: BoxFit.fill,
),
elevation: 5,
margin: EdgeInsets.all(10),
),
),
Expanded(
flex: 7,
child: Column(
children: [
ListTile(
title: Text(
searchController.results.data[index]["original_title"],
style: TextStyle(fontSize: 20.0),
),
subtitle: Text(
'By: ${searchController.results.data[index]["authors"]}',
style: TextStyle(fontSize: 15.0),
),
),
Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 5, 0, 0),
child: Text(
'(${searchController.results.data[index]["average_rating"]} avg)',
style: TextStyle(fontSize: 12.0),
),
),
],
),
Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(27, 10, 0, 0),
child: Text(
'Pub: ${searchController.results.data[index]["original_publication_year"]}',
style: TextStyle(fontSize: 12.0),
),
)
],
),
],
),
),
],
),
)
: searchController.requestPending
? Center(child: CircularProgressIndicator())
: ListTile(
title: Center(
child: RichText(
text: TextSpan(
text: searchController.results.data.length > 0
? "No more results"
: 'No results found',
style: TextStyle(color: Colors.black54, fontSize: 20, fontWeight: FontWeight.bold),
),
),
),
);
},
),
),
],
);
}
}
This code sets up a basic search interface where users can search for books, get autosuggestions, and view detailed results, including images, titles, authors, and publication years.
Customizing the Search Experience
Flutter Searchbox offers flexibility in customizing search experiences. You can tailor search widgets, adjust search parameters, and integrate additional features like filters and facets to refine results based on user preferences.
Optimizing Performance and User Experience
Optimizing your search interface is crucial for delivering a fast and responsive user experience. Consider implementing caching strategies, managing large datasets efficiently, and ensuring the UI remains smooth even under heavy search loads.
Summary
Building search UIs with Flutter Searchbox 4.0 is efficient and customizable, offering a rich set of features to create a seamless search experience. By following the steps in this guide, you can add powerful search capabilities into your Flutter app.
For more examples with facets, custom Search UI, and maps, explore the Flutter Searchbox documentation and start building search-powered apps today.
Subscribe to my newsletter
Read articles from Siddharth Kothari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Siddharth Kothari
Siddharth Kothari
CEO @reactivesearch, search engine dx