A simple Search Bar in Flutter 🔎 🦋

Ahmed Al-Zahrani
CodeChai
Published in
5 min readAug 29, 2018

One hurdle I recently overcame while developing a mobile Application using Flutter was the lack of a built in search bar Widget, analogous to a UISearchBar that is available when developing for iOS, a SearchView for android, or a SearchBar in React Native. I did manage to find a few Dart Packages that attempt to solve this issue, but elected to solve the issue myself in order to avoid relying on good maintenance/health of these third-party packages.

In this article, I will show you how to do the following:

  • Make API Requests in Dart using the dio package and the Star Wars api to populate our table with a list of the names of characters from Star Wars
  • Populate a ListView based on the data we receive from our API request
  • Add a search bar within our AppBar along the top of the view in order to filter our ListView

Tip: Before we start, navigate to your pubspec.yaml and add the Dio package as a dependency to your project like so:

dependencies:
flutter:
sdk: flutter
dio: 1.0.0

Here is an example of what the finished product will look like:

1. Add a few key data members to your State class

For this to work, the page that will house the list view needs to be a sub-class of a StatefulWidget. This is because, as the user enters search text or opens/dismisses the search bar, the widget needs to update it’s state to update the user interface. In my example, my Stateful Widget is called ‘Example Page’ and the class responsible for updating it’s state is called _ExamplePageState, I added the following data members to my _ExamplePageState class

class _ExamplePageState extends State<ExamplePage> {
// controls the text label we use as a search bar
final TextEditingController _filter = new TextEditingController();
final dio = new Dio(); // for http requests String _searchText = ""; List names = new List(); // names we get from API List filteredNames = new List(); // names filtered by search text Icon _searchIcon = new Icon(Icons.search); Widget _appBarTitle = new Text( 'Search Example' );}

2. Instantiate our lists when the page loads

To do this we need to override the Widget’s initState() method such that we can fetch the names of Star Wars characters and assign those results to our names and filteredNames lists. The code for that is surprisingly easy with dio, we simply create a function to do this work, and then we can call that inside our override of initState().

void _getNames() async {
final response = await dio.get('https://swapi.co/api/people');
List tempList = new List();
for (int i = 0; i < response.data['results'].length; i++) {
tempList.add(response.data['results'][i]);
}

setState(() {
names = tempList;
filteredNames = names;
});
}

3. Build our appBar with our with the search Icon present

It turns out this is relatively simple, it is just a regular app bar with a title and a leading icon, the actual magic comes in our design of the search icon’s onPressed method.

Here is the code for the callback function that activates when the icon is pressed:

void _searchPressed() {
setState(() {
if (this._searchIcon.icon == Icons.search) {
this._searchIcon = new Icon(Icons.close);
this._appBarTitle = new TextField(
controller: _filter,
decoration: new InputDecoration(
prefixIcon: new Icon(Icons.search),
hintText: 'Search...'
),
);
} else {
this._searchIcon = new Icon(Icons.search);
this._appBarTitle = new Text('Search Example');
filteredNames = names;
_filter.clear();
}
});
}

In the event that the if case executes, it means that the icon in our app bar is the search icon, meaning the app bar is in it’s default state. The function reacts by replacing the app bar title with a text field (where we enter our text) and replaces the icon with a close icon. Else, we are in that state and we revert to the default state.

4. Attach a listener to our TextEditingController

We want to override the default constructor for our page state such that it evaluates whether there is text currently in our search bar, and if so, appropriately sets our _searchText to whatever that input is so we can filter our list accordingly. The code for this constructor is below:

ExamplePageState() {
_filter.addListener(() {
if (_filter.text.isEmpty) {
setState(() {
_searchText = "";
filteredNames = names;
});
} else {
setState(() {
_searchText = _filter.text;
});
}
});
}

5. Build a table with the API information we’ve queried.

In step 2 we queried the Star Wars API and retrieved some names of characters in the star wars universe, we stored these in two lists, one called names and the other filteredNames.

The reason we did this is that we want to constantly be filtering out names IF there is search text, but we also want to keep the original list as is somewhere. Below is the code to filter the list and then build the listView with the results:

Widget _buildList() {
if (!(_searchText.isEmpty)) {
List tempList = new List();
for (int i = 0; i < filteredNames.length; i++) {
if (filteredNames[i]['name'].toLowerCase().contains(_searchText.toLowerCase())) {
tempList.add(filteredNames[i]);
}
}
filteredNames = tempList;
}
return ListView.builder(
itemCount: names == null ? 0 : filteredNames.length,
itemBuilder: (BuildContext context, int index) {
return new ListTile(
title: Text(filteredNames[index]['name']),
onTap: () => print(filteredNames[index]['name']),
);
},
);
}

And Voila! You’ve implemented your very own search bar in Flutter with just a text field and a couple of icons! 💥

The full source code for this project unedited can be found on my Github.

The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.

--

--

Ahmed Al-Zahrani
CodeChai
Writer for

Computer Science Undergraduate at Carleton University. Back-end Developer with a growing interest in mobile, particularly Flutter