You are currently viewing Flutter SearchView Examples – ListView Search/Filter

Flutter SearchView Examples – ListView Search/Filter

Flutter Searchview and Listview tutorial examples.

In this piece we want to look at some of the best and easiest Flutter SearchView examples.

Example 1 - Search Filter ListView of Cards

We see how to search/filter a listview in flutter using a searchview. That so called searchview is actually a custom textfield. We will use a TextEditingController to notify us of text changeson our textfield. Thus this allows us easily search our data.

Flutter SearchView Example

That data is actually bound from a simple list. And in fact we will maintain two lists:

  1. First List - The actual data source. This never changes.
  2. Second List - This will hold the filter results. For example if you search and have 5 results from a list of a hundred, then we hold those 5 results in this second list.

The search itself is rather simple. We simply use the contains() method of the string class. However we have to make sure we have case consistency, such that for example our query is in lowercase then the data also has to be in lowercase.

Demo

Here are the demo for this project:

Flutter SearchView Example

Video Tutorial

If you prefer a video tutorial for this you can watch it here in our YouTube Channel:

(a). pubspec.yaml

We are not using any third party library.

Instead here we will have the name and description of app.

name: mr_searchview
description: Flutter SearchView example project.
dependencies:
  flutter:
    sdk: flutter
  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
dev_dependencies:
  flutter_test:
    sdk: flutter

(b). main.dart

Here's our full main.dart code.

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
//Our MyApp class. Represents our application
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "ListView SearchView",
      home: new Home(),
      theme: ThemeData(primaryColor: Colors.orange),
    );
  }
}
//Represents the Homepage widget
class Home extends StatefulWidget {
  //<code>createState() will create the mutable state for this widget at
  //a given location in the tree.
  @override
  _HomeState createState() => _HomeState();
}
//Our Home state, the logic and internal state for a StatefulWidget.
class _HomeState extends State<Home> {
  //A controller for an editable text field.
  //Whenever the user modifies a text field with an associated
  //TextEditingController, the text field updates value and the
  //controller notifies its listeners.
  var _searchview = new TextEditingController();
  bool _firstSearch = true;
  String _query = "";
  List<String> _nebulae;
  List<String> _filterList;
  @override
  void initState() {
    super.initState();
    _nebulae = new List<String>();
    _nebulae = [
      "Orion",
      "Boomerang",
      "Cat's Eye",
      "Pelican",
      "Ghost Head",
      "Witch Head",
      "Snake",
      "Ant",
      "Bernad 68",
      "Flame",
      "Eagle",
      "Horse Head",
      "Elephant's Trunk",
      "Butterfly"
    ];
    _nebulae.sort();
  }
  _HomeState() {
    //Register a closure to be called when the object changes.
    _searchview.addListener(() {
      if (_searchview.text.isEmpty) {
        //Notify the framework that the internal state of this object has changed.
        setState(() {
          _firstSearch = true;
          _query = "";
        });
      } else {
        setState(() {
          _firstSearch = false;
          _query = _searchview.text;
        });
      }
    });
  }
//Build our Home widget
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text("SearchView ListView"),
      ),
      body: new Container(
        margin: EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0),
        child: new Column(
          children: <Widget>[
           _createSearchView(),
            _firstSearch ? _createListView() : _performSearch()
          ],
        ),
      ),
    );
  }
 //Create a SearchView
  Widget _createSearchView() {
    return new Container(
      decoration: BoxDecoration(border: Border.all(width: 1.0)),
      child: new TextField(
        controller: _searchview,
        decoration: InputDecoration(
          hintText: "Search",
          hintStyle: new TextStyle(color: Colors.grey[300]),
        ),
        textAlign: TextAlign.center,
      ),
    );
  }
  //Create a ListView widget
  Widget _createListView() {
    return new Flexible(
      child: new ListView.builder(
          itemCount: _nebulae.length,
          itemBuilder: (BuildContext context, int index) {
            return new Card(
              color: Colors.white,
              elevation: 5.0,
              child: new Container(
                margin: EdgeInsets.all(15.0),
                child: new Text("${_nebulae[index]}"),
              ),
            );
          }),
    );
  }
  //Perform actual search
  Widget _performSearch() {
    _filterList = new List<String>();
    for (int i = 0; i < _nebulae.length; i++) {
      var item = _nebulae[i];
      if (item.toLowerCase().contains(_query.toLowerCase())) {
        _filterList.add(item);
      }
    }
    return _createFilteredListView();
  }
  //Create the Filtered ListView
  Widget _createFilteredListView() {
    return new Flexible(
      child: new ListView.builder(
          itemCount: _filterList.length,
          itemBuilder: (BuildContext context, int index) {
            return new Card(
              color: Colors.white,
              elevation: 5.0,
              child: new Container(
                margin: EdgeInsets.all(15.0),
                child: new Text("${_filterList[index]}"),
              ),
            );
          }),
    );
  }
}

How to Download and Run.

Just copy this code into main.dart file. There is no setup required.

Example 2 - Search Filter ListView From AppBar/Toolbar

This is the second flutter searchview example. It's also easy to understand and will help implement search filter in flutter using Dart Programming of course. This example also doesn't require any setup or dependencies. This example will involve rendering a searchview in the toolbar or appBar of our application.

Let's start.

Demo

Here is demo.

Flutter SearchView

Flutter AppBar SearchView

(a). search_list.dart

This file will define us a stateful widget to represent our searchable listview.'

Add Imports

Start by importing material.dart:

import 'package:flutter/material.dart';

Create Stateful Widget

Then create the widget by extending the StatefulWidget:

class SearchList extends StatefulWidget {

and defining the constructor:

  SearchList({ Key key }) : super(key: key);

then finally overriding the createState() method:

  @override
  _SearchListState createState() => new _SearchListState();
}

Create State class

Start by extending the State class:

class _SearchListState extends State<SearchList>
{

Then define instance fields:

  Widget appBarTitle = new Text("Search Sample", style: new TextStyle(color: Colors.white),);
  Icon actionIcon = new Icon(Icons.search, color: Colors.white,);
  final key = new GlobalKey<ScaffoldState>();
  final TextEditingController _searchQuery = new TextEditingController();
  List<String> _list;
  bool _IsSearching;
  String _searchText = "";

The instance fields as you can see include the appBar title, icon, TextEditingController etc.

In the constructor attach a listener to the TextEditingController. This allows us to be notified of text change events in the editing fields as the user types:

  _SearchListState() {
    _searchQuery.addListener(() {
      if (_searchQuery.text.isEmpty) {
        setState(() {
          _IsSearching = false;
          _searchText = "";
        });
      }
      else {
        setState(() {
          _IsSearching = true;
          _searchText = _searchQuery.text;
        });
      }
    });
  }

Now override the initState() method:

  @override
  void initState() {
    super.initState();
    _IsSearching = false;
    init();
  }

Add List of items to act as the data source:

  void init() {
    _list = List();
    _list.add("Google");
    _list.add("IOS");
    _list.add("Andorid");
    _list.add("Dart");
    _list.add("Flutter");
    _list.add("Python");
    _list.add("React");
    _list.add("Xamarin");
    _list.add("Kotlin");
    _list.add("Java");
    _list.add("RxAndroid");
  }

Override the build() method of this state class:

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: key,
      appBar: buildBar(context),
      body: new ListView(
        padding: new EdgeInsets.symmetric(vertical: 8.0),
        children: _IsSearching ? _buildSearchList() : _buildList(),
      ),
    );
  }

In it you can see we are building our widget by specifying the appBar as well as the body which in this case will contain a ListView.

Then two helper methods returning List of data:

  List<ChildItem> _buildList() {
    return _list.map((contact) => new ChildItem(contact)).toList();
  }
  List<ChildItem> _buildSearchList() {
    if (_searchText.isEmpty) {
      return _list.map((contact) => new ChildItem(contact))
          .toList();
    }
    else {
      List<String> _searchList = List();
      for (int i = 0; i < _list.length; i++) {
        String  name = _list.elementAt(i);
        if (name.toLowerCase().contains(_searchText.toLowerCase())) {
          _searchList.add(name);
        }
      }
      return _searchList.map((contact) => new ChildItem(contact))
          .toList();
    }
  }

Then a helper method to help in constructing the AppBar widget:

  Widget buildBar(BuildContext context) {
    return new AppBar(
        centerTitle: true,
        title: appBarTitle,
        actions: <Widget>[
          new IconButton(icon: actionIcon, onPressed: () {
            setState(() {
              if (this.actionIcon.icon == Icons.search) {
                this.actionIcon = new Icon(Icons.close, color: Colors.white,);
                this.appBarTitle = new TextField(
                  controller: _searchQuery,
                  style: new TextStyle(
                    color: Colors.white,
                  ),
                  decoration: new InputDecoration(
                      prefixIcon: new Icon(Icons.search, color: Colors.white),
                      hintText: "Search...",
                      hintStyle: new TextStyle(color: Colors.white)
                  ),
                );
                _handleSearchStart();
              }
              else {
                _handleSearchEnd();
              }
            });
          },),
        ]
    );
  }

That appBar widget will have a searchview in it as you can see in the above method.

Then lastly for this state class, create methods to handle search start and search end:

  void _handleSearchStart() {
    setState(() {
      _IsSearching = true;
    });
  }
  void _handleSearchEnd() {
    setState(() {
      this.actionIcon = new Icon(Icons.search, color: Colors.white,);
      this.appBarTitle =
      new Text("Search Sample", style: new TextStyle(color: Colors.white),);
      _IsSearching = false;
      _searchQuery.clear();
    });
  }
}

That is the end of the State class.

Now below it create another class called childItem. It's also a widget representing a single ListView item:


class ChildItem extends StatelessWidget {
  final String name;
  ChildItem(this.name);
  @override
  Widget build(BuildContext context) {
    return new ListTile(title: new Text(this.name));
  }
}

(b). main.dart

Come in the main file and add the following code:

import 'package:flutter/material.dart';
import 'package:flutter_search_app/search_list.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Search',
      debugShowCheckedModeBanner: false,
      theme: new ThemeData(
        brightness: Brightness.light,
        primarySwatch:Colors.yellow,
        primaryColor: Color(0xFFFFBB54),
        accentColor: Color(0xFFECEFF1),
      ),
      home: new SearchList(),
    );
  }
}

That's it.

Special Thanks to @MageshPandian20 for this wonderful example.

Download Project.

Have a good day.

Leave a Reply