I have created a page in which there is search bar and then the listview builder which is building items of List coming from provider class. When I tap on search bar, the keyboard appears ,suddenly disappears and page refreshes. when page is refreshed, first it shows circularprogressIndicator
and then regular ListView.builder
.
Kindly Help.
Thank you in advance!
import 'package:carstraders/models/cars.dart';
import 'package:carstraders/providers/cars_provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class SearchPage extends StatefulWidget {
static const routeName = 'search-page';
const SearchPage({Key? key}) : super(key: key);
@override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
var search = TextEditingController();
var list = [];
List<Cars> allItems = [];
String query = '';
bool isFirstTime = true;
@override
void initState() {
allItems = Provider.of<CarsProvider>(context, listen: false).list;
list = allItems;
// TODO: implement initState
super.initState();
}
this is the function which searches the items and updates the list
void searchItem(String val) {
final searched = allItems.where((element) {
final transmission = element.transmission.toLowerCase();
final model = element.model.toLowerCase();
final make = element.make.toLowerCase();
final price = element.price.toString();
final engine = element.engine.toString();
final searchedVal = val.toLowerCase();
if (model.contains(searchedVal) ||
make.contains(searchedVal) ||
price.contains(searchedVal) ||
engine.contains(searchedVal) ||
transmission.contains(searchedVal)) {
return true;
}
return false;
}).toList();
setState(() {
list = searched;
query = val;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Search'),
),
body: FutureBuilder(
future: Provider.of<CarsProvider>(context,listen: false).fetchAndSet(),
builder: (ctx, snap) => snap.connectionState == ConnectionState.waiting
? const Center(
child: CircularProgressIndicator(),
)
: Column(children: [
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: searchItem,
// style: TextStyle(color: Colors.white),
controller: search,
key: const Key('search'),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
label: const Text('Search'),
suffixIcon: query.isEmpty
? null
: GestureDetector(
child: const Icon(Icons.close),
onTap: () {
setState(() {
query = '';
searchItem('');
search.clear();
FocusScope.of(context).unfocus();
});
},
),
prefixIcon: const Icon(Icons.search_sharp),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey,
width: 0.5,
),
),
),
),
),
),
],
),
Expanded(
child: ListView.builder(
itemBuilder: (ctx, i) => buildItem(list[i], context),
itemCount: list.length,
),
)
]),
),
);
}
}
this widget builds the item of listview.builder
Widget buildItem(Cars item, BuildContext context) {
return GestureDetector(
onTap: () =>
Navigator.of(context).pushNamed('search-item-detail', arguments: item),
child: Card(
elevation: 5,
child: Row(
// mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.43,
child: Image.network(item.img),
),
SizedBox(width: MediaQuery.of(context).size.width * 0.02),
Column(
children: [
Text(
item.year.toString() + ' ' + item.make + ' ' + item.model,
style: const TextStyle(
color: Colors.blueAccent,
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.5,
child: const Divider(color: Colors.black)),
Row(
children: [
Text('${item.mileage} mi'),
Container(
margin: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.03),
decoration: const BoxDecoration(
border: Border(left: BorderSide(color: Colors.grey))),
child: const Text('')),
Text('£${item.price}')
],
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.5,
child: const Divider(color: Colors.black)),
Row(
children: [
Text(' ' + item.plateNo),
Container(
margin: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.03),
child: const Text(''),
decoration: const BoxDecoration(
border: Border(left: BorderSide(color: Colors.grey))),
),
Text(item.transmission)
],
)
],
)
],
),
),
);
}