Search List in Flutter:
Search List in Flutter:Flutter search in ListView is a powerful and essential functionality to have in any app that deals with large amounts of data. In this blog post, we will guide you through the process of implementing search functionality in a Flutter app using ListView.
StatefulWidget are mutable by nature where we want to change our widgets for multiple times we make use of this StatefulWidget
So first i am creating List of items as below .
List<String> foodList = [
'Apple',
'Black Beans',
'Pinto beans',
'White Beans',
'Orange',
'Berries',
'tomatoes',
'Lemons',
'Mangoes',
'Dates',
'Avocados',
'Chickpeas',
'Green lentils',
'Split Peas',
'Rice',
'Oats',
'Quinoa',
'Pasta',
'Sparkling water',
'Coconut water',
'Herbal tea',
'Kombucha',
'Almonds',
'Peannuts',
'Chia seeds',
'Flax seeds',
'Canned tomatoes',
'Olive oil',
'Broccoli',
'Onions',
'Garlic',
'Carots',
'Leafy greens',
'Meat',
];
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. Listeners can then read the text and selection properties to learn what the user has typed or how the selection has updated.
TextEditingController? _textEditingController = TextEditingController();
An object that can use a stateful widget to obtain the keyboard focus and to handle keyboard events.
final FocusNode _textFocusNode = FocusNode();
Dispose is a method triggers whenever the created object from the stateful widget removes permanently from the widget tree. It is generally overridden and calls only when the state object is destroyed. Dispose releases the memory allocated to the existing variables of the state. It is only use in a stateful widget because you cannot change the state of a stateless widget.
void dispose() {
_textFocusNode.dispose();
_textEditingController!.dispose();
super.dispose();
}
In some cases, it’s useful to run a callback function every time the text in a text field changes. For example, you might want to build a search screen with autocomplete functionality where you want to update the results as the user types.
How do you run a callback function every time the text changes? With Flutter, you have two options:
- Supply an
onChanged()
callback to aTextField
or aTextFormField
. - Use a
TextEditingController
.
It’s important to use characters when dealing with user input, as text may contain complex characters. This ensures that every character is counted correctly as they appear to the user.
TextField(
onChanged: (text) {
print('First text field: $text (${text.characters.length})');
},
),
TextField(
controller: _textEditingController,
focusNode: _textFocusNode,
cursorColor: Colors.black,
decoration: InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
hintText: 'Search here',
contentPadding: EdgeInsets.all(8)),
onChanged: (value) {
setState(() {
foodListSearch = foodList
.where(
(element) => element.contains(value.toLowerCase()))
.toList();
if (_textEditingController!.text.isNotEmpty &&
foodListSearch!.length == 0) {
print('foodListSearch length ${foodListSearch!.length}');
}
});
},
),
Empty List
_textEditingController!.text.isNotEmpty &&
foodListSearch!.length == 0
? Center(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.search_off,
size: 160,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'No results found,\nPlease try different keyword',
style: TextStyle(
fontSize: 30, fontWeight: FontWeight.w600),
),
),
],
),
),
)
List the element
ListView.builder(
itemCount: _textEditingController!.text.isNotEmpty
? foodListSearch!.length
: foodList.length,
itemBuilder: (ctx, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
CircleAvatar(
child: Icon(Icons.food_bank),
),
SizedBox(
width: 10,
),
Text(_textEditingController!.text.isNotEmpty
? foodListSearch![index]
: foodList[index]),
],
),
);
})
Full Code:Search List in Flutter
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<String> foodList = [
'Apple',
'Black Beans',
'Pinto beans',
'White Beans',
'Orange',
'Berries',
'tomatoes',
'Lemons',
'Mangoes',
'Dates',
'Avocados',
'Chickpeas',
'Green lentils',
'Split Peas',
'Rice',
'Oats',
'Quinoa',
'Pasta',
'Sparkling water',
'Coconut water',
'Herbal tea',
'Kombucha',
'Almonds',
'Peannuts',
'Chia seeds',
'Flax seeds',
'Canned tomatoes',
'Olive oil',
'Broccoli',
'Onions',
'Garlic',
'Carots',
'Leafy greens',
'Meat',
];
List<String>? foodListSearch;
final FocusNode _textFocusNode = FocusNode();
TextEditingController? _textEditingController = TextEditingController();
@override
void dispose() {
_textFocusNode.dispose();
_textEditingController!.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue.shade300,
title: Container(
decoration: BoxDecoration(
color: Colors.blue.shade200,
borderRadius: BorderRadius.circular(20)),
child:
TextField(
controller: _textEditingController,
focusNode: _textFocusNode,
cursorColor: Colors.black,
decoration: InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
hintText: 'Search here',
contentPadding: EdgeInsets.all(8)),
onChanged: (value) {
setState(() {
foodListSearch = foodList
.where(
(element) => element.contains(value.toLowerCase()))
.toList();
if (_textEditingController!.text.isNotEmpty &&
foodListSearch!.length == 0) {
print('foodListSearch length ${foodListSearch!.length}');
}
});
},
),
)),
body: _textEditingController!.text.isNotEmpty &&
foodListSearch!.length == 0
? Center(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.search_off,
size: 160,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'No results found,\nPlease try different keyword',
style: TextStyle(
fontSize: 30, fontWeight: FontWeight.w600),
),
),
],
),
),
)
: ListView.builder(
itemCount: _textEditingController!.text.isNotEmpty
? foodListSearch!.length
: foodList.length,
itemBuilder: (ctx, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
CircleAvatar(
child: Icon(Icons.food_bank),
),
SizedBox(
width: 10,
),
Text(_textEditingController!.text.isNotEmpty
? foodListSearch![index]
: foodList[index]),
],
),
);
}));
}
}
For More: To know about AlertDialog Flutter
Leave a Reply