Hello,

In our daily life, we build may flutter application which has ListView in it.

So, Let's see an example how to implement search functionality within the list

Let's Create a DataSource

final items = List<String>.generate(10000, (i) => "Item $i");

Let’s Create a ListWidget from DataSource

ListView.builder(

itemCount: items.length,

itemBuilder: (context, index) {

return ListTile(

title: Text('${items[index]}'),

);

},

);

Here our example app with ListView

import 'package:flutter/foundation.dart';

import 'package:flutter/material.dart';



void main() {

runApp(MyApp(

items: List<String>.generate(10000, (i) => "Item $i"),

));

}



class MyApp extends StatelessWidget {

final List<String> items;



MyApp({Key key, @required this.items}) : super(key: key);



@override

Widget build(BuildContext context) {

final title = 'Long List';



return MaterialApp(

title: title,

home: Scaffold(

appBar: AppBar(

title: Text(title),

),

body: ListView.builder(

itemCount: items.length,

itemBuilder: (context, index) {

return ListTile(

title: Text('${items[index]}'),

);

},

),

),

);

}

}

example output

Want to read this story later? Save it in Journal.

We need to convert StateLessWidget to StateFullWidget

Let’s Add a search bar on the top of the ListView

TextField(

controller: editingController,

decoration: InputDecoration(

labelText: "Search",

hintText: "Search",

prefixIcon: Icon(Icons.search),

border: OutlineInputBorder(

borderRadius: BorderRadius.all(Radius.circular(25.0)))),

),

Our code for UI showing a search bar and ListView with 1000 items

import 'package:flutter/material.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 Demo',

theme: new ThemeData(

primarySwatch: Colors.blue,

),

home: new MyHomePage(title: 'ListView with Search'),

);

}

}



class MyHomePage extends StatefulWidget {

MyHomePage({Key key, this.title}) : super(key: key);

final String title;



@override

_MyHomePageState createState() => new _MyHomePageState();

}



class _MyHomePageState extends State<MyHomePage> {

TextEditingController editingController = TextEditingController();



final duplicateItems = List<String>.generate(10000, (i) => "Item $i");

var items = List<String>();



@override

void initState() {

items.addAll(duplicateItems);

super.initState();

}

@override

Widget build(BuildContext context) {

return new Scaffold(

appBar: new AppBar(

title: new Text(widget.title),

),

body: Container(

child: Column(

children: <Widget>[

Padding(

padding: const EdgeInsets.all(8.0),

child: TextField(

onChanged: (value) {



},

controller: editingController,

decoration: InputDecoration(

labelText: "Search",

hintText: "Search",

prefixIcon: Icon(Icons.search),

border: OutlineInputBorder(

borderRadius: BorderRadius.all(Radius.circular(25.0)))),

),

),

Expanded(

child: ListView.builder(

shrinkWrap: true,

itemCount: items.length,

itemBuilder: (context, index) {

return ListTile(

title: Text('${items[index]}'),

);

},

),

),

],

),

),

);

}

}

In the above code, we used we have taken two List<String> variables one to store the List<String> Permanently and other will change based on the Search Query

final duplicateItems = List<String>.generate(10000, (i) => "Item $i");

var items = List<String>();

Now Lets implement out filter Function which is responsible for searching and listing the new list items

void filterSearchResults(String query) {

List<String> dummySearchList = List<String>();

dummySearchList.addAll(duplicateItems);

if(query.isNotEmpty) {

List<String> dummyListData = List<String>();

dummySearchList.forEach((item) {

if(item.contains(query)) {

dummyListData.add(item);

}

});

setState(() {

items.clear();

items.addAll(dummyListData);

});

return;

} else {

setState(() {

items.clear();

items.addAll(duplicateItems);

});

}

}

We call this filterSearchResults function in onChanged of TextField

onChanged: (value) {

filterSearchResults(value);

},

Our Final main.dart file will be as below

import 'package:flutter/material.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 Demo',

theme: new ThemeData(

primarySwatch: Colors.blue,

),

home: new MyHomePage(title: 'ListView with Search),

);

}

}



class MyHomePage extends StatefulWidget {

MyHomePage({Key key, this.title}) : super(key: key);

final String title;



@override

_MyHomePageState createState() => new _MyHomePageState();

}



class _MyHomePageState extends State<MyHomePage> {

TextEditingController editingController = TextEditingController();



final duplicateItems = List<String>.generate(10000, (i) => "Item $i");

var items = List<String>();



@override

void initState() {

items.addAll(duplicateItems);

super.initState();

}



void filterSearchResults(String query) {

List<String> dummySearchList = List<String>();

dummySearchList.addAll(duplicateItems);

if(query.isNotEmpty) {

List<String> dummyListData = List<String>();

dummySearchList.forEach((item) {

if(item.contains(query)) {

dummyListData.add(item);

}

});

setState(() {

items.clear();

items.addAll(dummyListData);

});

return;

} else {

setState(() {

items.clear();

items.addAll(duplicateItems);

});

}



}



@override

Widget build(BuildContext context) {

return new Scaffold(

appBar: new AppBar(

title: new Text(widget.title),

),

body: Container(

child: Column(

children: <Widget>[

Padding(

padding: const EdgeInsets.all(8.0),

child: TextField(

onChanged: (value) {

filterSearchResults(value);

},

controller: editingController,

decoration: InputDecoration(

labelText: "Search",

hintText: "Search",

prefixIcon: Icon(Icons.search),

border: OutlineInputBorder(

borderRadius: BorderRadius.all(Radius.circular(25.0)))),

),

),

Expanded(

child: ListView.builder(

shrinkWrap: true,

itemCount: items.length,

itemBuilder: (context, index) {

return ListTile(

title: Text('${items[index]}'),

);

},

),

),

],

),

),

);

}

}

final output

Thanks for your time.

Hope you like it, if yes clap & share.