Flutter detail search function
So you have to wrap your code with a future builder that will first await your data from Firebase.
Then you have to display any GridView item that fulfill your condition (the string contains what the user has typed, that is here a constant: categorySearched
). Additionally you may want to add the lower method to make it case insensitive.
You will use a gridview.builder for that goal.
Then you also need to map each category with the corresponding icon: Map<String, String> imageMap = {'Education': 'educationicon', 'Business': 'businessicon'}; // etc.
Hopefully you should be able to make your code working fully with little tweaks here and there. Let me know if you need more help.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class LevelCategoryMap {
final String title;
final String level;
final String region;
LevelCategoryMap(this.title, this.level, this.region);
Map<String, dynamic> toMap() {
return {
'title': title,
'level': level,
'description': region
};
}
@override
String toString() {
return 'LevelCategoryMap{level: $level, description: $region';
}
}
class _LevelPageState extends State<LevelPage> {
final String categorySearched = "fishing";
String level = 1;
@override
Widget build(BuildContext context) {
final dbCollectionSnapshot = Firestore
.instance
.collection("Level$level")
.where('desc', )
.snapshots(); // retrieve
return StreamBuilder<QuerySnapshot>(
stream: dbCollectionSnapshot,
builder: (context, snapshot) {
List<LevelCategoryMap> levelCategory;
if (!snapshot.hasData || snapshot.data == null) return CircularProgressIndicator();
snapshot.data.documents.forEach((element) {
levelCategory.add(LevelCategoryMap(element.documentID, level, element.data['desc']));
})
final int resultsLen = levelCategory.length;
return new Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
title: Text(widget.level.data["region"]),
centerTitle: true,
),
body: ListView(shrinkWrap: true, children: <Widget>[
Container(
child: ListTile(
title: Text(
'Current Level ' + widget.level.data["level"].toString(),
style: TextStyle(
color: widget.level.data["level"] == 5
? Colors.red[900]
: widget.level.data["level"] == 4
? Colors.orange[900]
: widget.level.data["level"] == 3
? Colors.brown[300]
: widget.level.data["level"] == 2
? Colors.blue[300]
: widget.level.data["level"] == 1
? Colors.green[300]
: Colors.black,
fontSize: 25,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
),
Center(
child: GridView.builder(
itemCount: resultsLen,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (context, index) {
final String description = levelCategory[index].region;
if (description.contains(categorySearched))
return myGridItem(context, index, levelCategory[index]);
//: ClassifiedThumbnail(connection, capitalize(widget.city), snapshot.data[index]);
})),
]));
}
else
return CircularProgressIndicator();
});
}
}
Widget myGridItem(context, index, LevelCategoryMap myLevelCategory) {
Map<String, String> imageMap = {'Education': 'educationicon', 'Business': 'businessicon'}; // etc.
return ListTile(
title: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.grey,
),
child: InkWell(
enableFeedback: true,
child: Image.asset('assets/images/' + imageMap[myLevelCategory.title] + '.png'),
onTap: () => {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CategoryPage(
text1: myLevelCategory.title, // I assume level is the name with education
text2: myLevelCategory.region,
text3: myLevelCategory.level)))
},
splashColor: Colors.white,
borderRadius: BorderRadius.circular(20),
)),
subtitle: Text(myLevelCategory.title,
style: TextStyle(
color: Colors.white,
fontSize: 10,
),
textAlign: TextAlign.center),
);
This will work with firebase. However note that you are downloading everything are doing the work on the mobile. In your case it's not a big deal since you only have 10 categories with only text. However if you wanted to make a search-based query in firebase you would have to use a third party service as stated here: https://firebase.google.com/docs/firestore/solutions/search
Comments
-
PKirby over 1 year
I currently have a flutter app which displays clickable images within a gridview.
After selecting an image, it takes you to a detailed page which provides more info on the selected category:
I now need to build search functionality which would filter based on the Category Detail. So if I search for "Fishing", the gridview filters displaying "Agriculture" and whatever other Category detail contains that word.
I currently use Firebase to return the Category detail whenever a user selects the Category so I assume that the search would have to be linked to my firebase?
I've tried looking for answers on the web but none caters for my specific requirement.
UPDATE Included Gridview Page Code:
class _LevelPageState extends State<LevelPage> { @override Widget build(BuildContext context) { return new Scaffold( appBar: AppBar( backgroundColor: Colors.grey, title: Text(widget.level.data["region"]), centerTitle: true, ), body: ListView(shrinkWrap: true, children: <Widget>[ Container( child: ListTile( title: Text( 'Current Level ' + widget.level.data["level"].toString(), style: TextStyle( color: widget.level.data["level"] == 5 ? Colors.red[900] : widget.level.data["level"] == 4 ? Colors.orange[900] : widget.level.data["level"] == 3 ? Colors.brown[300] : widget.level.data["level"] == 2 ? Colors.blue[300] : widget.level.data["level"] == 1 ? Colors.green[300] : Colors.black, fontSize: 25, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), ), ), Container( height: (MediaQuery.of(context).size.height), padding: EdgeInsets.all(10), child: GridView.count( shrinkWrap: true, physics: ScrollPhysics(), mainAxisSpacing: 40, crossAxisSpacing: 20, crossAxisCount: 3, childAspectRatio: MediaQuery.of(context).size.height / 400, children: <Widget>[ ListTile( title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: InkWell( enableFeedback: true, child: Image.asset('assets/images/mediaicon.png'), onTap: () => { Navigator.of(context).push(MaterialPageRoute( builder: (context) => CategoryPage( text1: 'Media', text2: widget.level.data["region"].toString(), text3: widget.level.data["level"].toString()))) }, splashColor: Colors.white, borderRadius: BorderRadius.circular(20), )), subtitle: Text('Media', style: TextStyle( color: Colors.white, fontSize: 10, ), textAlign: TextAlign.center), ), ListTile( title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: InkWell( enableFeedback: true, child: Image.asset('assets/images/mobileanditicon.png'), onTap: () => { Navigator.of(context).push(MaterialPageRoute( builder: (context) => CategoryPage( text1: 'Info and Comms', text2: widget.level.data["region"].toString(), text3: widget.level.data["level"].toString()))) }, splashColor: Colors.white, borderRadius: BorderRadius.circular(20), )), subtitle: Text('Info and Comms', style: TextStyle( color: Colors.white, fontSize: 10, ), textAlign: TextAlign.center), ), ListTile( title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: InkWell( enableFeedback: true, child: Image.asset('assets/images/utilitiesicon.png'), onTap: () => { Navigator.of(context).push(MaterialPageRoute( builder: (context) => CategoryPage( text1: 'Utilities', text2: widget.level.data["region"].toString(), text3: widget.level.data["level"].toString()))) }, splashColor: Colors.white, borderRadius: BorderRadius.circular(20), )), subtitle: Text('Utilities', style: TextStyle( color: Colors.white, fontSize: 10, ), textAlign: TextAlign.center), ), ListTile( title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: InkWell( enableFeedback: true, child: Image.asset('assets/images/educationicon.png'), onTap: () => { Navigator.of(context).push(MaterialPageRoute( builder: (context) => CategoryPage( text1: 'Education', text2: widget.level.data["region"].toString(), text3: widget.level.data["level"].toString()))) }, splashColor: Colors.white, borderRadius: BorderRadius.circular(20), )), subtitle: Text('Education', style: TextStyle( color: Colors.white, fontSize: 10, ), textAlign: TextAlign.center), ), ListTile( title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: InkWell( enableFeedback: true, child: Image.asset('assets/images/repairsicon.png'), onTap: () => { Navigator.of(context).push(MaterialPageRoute( builder: (context) => CategoryPage( text1: 'Repairs', text2: widget.level.data["region"].toString(), text3: widget.level.data["level"].toString()))) }, splashColor: Colors.white, borderRadius: BorderRadius.circular(20), )), subtitle: Text('Repairs', style: TextStyle( color: Colors.white, fontSize: 10, ), textAlign: TextAlign.center), ), ListTile( title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.grey, ), child: InkWell( enableFeedback: true, child: Image.asset('assets/images/domestichelpicon.png'), onTap: () => { Navigator.of(context).push(MaterialPageRoute( builder: (context) => CategoryPage( text1: 'Domestic Help', text2: widget.level.data["region"].toString(), text3: widget.level.data["level"].toString()))) }, splashColor: Colors.white, borderRadius: BorderRadius.circular(20), )), subtitle: Text('Domestic Help', style: TextStyle( color: Colors.white, fontSize: 10, ), textAlign: TextAlign.center), ), ], ), ), ])); } }
I have adjusted the above code to only include 6 of the gridview images to shorten the code.
-
PKirby almost 4 yearsThanks for your answer. I am geeting a "Undefined name 'FirebaseDatabase'. Try correcting the name to one that is defined, or defining the name." on 'final dbRef = FirebaseDatabase.instance.reference().child("levelcategory");'
-
Antonin GAVREL almost 4 yearsYes it depends on how you defined names of your data in your firebase database. I am using PostgresQL so I camt help you much on this part, you can google 'future flutter firebase tutorial" if you have never done it to get started and hopefully you will be able to have your code working
-
PKirby almost 4 yearsThanks, I've replace it with 'widget.level.data["level"];' but now getting a 'NoSuchMethodError" - "Class 'int' has no instance getter 'once'. Receiver: 3 Tried calling: once"
-
PKirby almost 4 yearsI've added my firebase data structure if that would help? .. I am a bit lost as to where to go from here...