I cannot retrieve and view data from Firestore Flutter - firebase

#HOME: this is home linked to FeatureProducts()
And I cannot retrieve data "product", it always return nil.
I want to retrieve data from Firebase into the Listview.
this is my firebase cloud fire store Image of Firebase Database
i try many time with many ways and all codes doesn't give any errors, but When i run the app and open the activity the data cannot show they will be empty,
import 'package:farmers_ecommerce/commons/common.dart';
import 'package:farmers_ecommerce/db/product.dart';
import 'package:farmers_ecommerce/pages/product_search.dart';
import 'package:farmers_ecommerce/provider/product.dart';
import 'package:farmers_ecommerce/provider/user_provider.dart';
import 'package:farmers_ecommerce/widget/featured_products.dart';
import 'package:farmers_ecommerce/widget/product_card.dart';
import 'package:farmers_ecommerce/widgets/custom_text.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'cart.dart';
import 'order.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _key = GlobalKey<ScaffoldState>();
ProductServices _productServices = ProductServices();
#override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
final productProvider = Provider.of<ProductProvider>(context);
return Scaffold(
key: _key,
backgroundColor: Colors.white,
endDrawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.black),
accountName: CustomText(
text: userProvider.userModel?.name ?? "username lading...",
color: Colors.white,
weight: FontWeight.bold,
size: 18,
),
accountEmail: CustomText(
text: userProvider.userModel?.email ?? "email loading...",
color: Colors.white,
),
),
ListTile(
onTap: () async{
await userProvider.getOrders();
changeScreen(context, OrdersScreen());
},
leading: Icon(Icons.bookmark_border),
title: CustomText(text: "My orders"),
),
ListTile(
onTap: () async{
userProvider.signOut();
},
leading: Icon(Icons.exit_to_app),
title: CustomText(text: "Log out"),
),
],
),
),
body: SafeArea(
child: ListView(
children: <Widget>[
// Custom App bar
Stack(
children: <Widget>[
Positioned(
top: 10,
right: 20,
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: () {
_key.currentState.openEndDrawer();
},
child: Icon(Icons.menu))),
),
Positioned(
top: 10,
right: 60,
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: (){
changeScreen(context, CartScreen());
},
child: Icon(Icons.shopping_cart))),
),
Positioned(
top: 10,
right: 100,
child: Align(
alignment: Alignment.topRight, child: GestureDetector(
onTap: (){
_key.currentState.showSnackBar(SnackBar(
content: Text("User profile")));
},
child: Icon(Icons.person))),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'What are\nyou Shopping for?',
style: TextStyle(
fontSize: 30,
color: Colors.black.withOpacity(0.6),
fontWeight: FontWeight.w400),
),
),
],
),
// Search Text field
// Search(),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(20),
bottomLeft: Radius.circular(20))),
child: Padding(
padding: const EdgeInsets.only(
top: 8, left: 8, right: 8, bottom: 10),
child: Container(
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.2),
borderRadius: BorderRadius.circular(20),
),
child: ListTile(
leading: Icon(
Icons.search,
color: Colors.black,
),
title: TextField(
textInputAction: TextInputAction.search,
onSubmitted: (pattern)async{
await productProvider.search(productName: pattern);
changeScreen(context, ProductSearchScreen());
},
decoration: InputDecoration(
hintText: "fashion....",
border: InputBorder.none,
),
),
),
),
),
),
// featured products
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text('Featured products')),
),
],
),
FeaturedProducts(),
**this is the feature products. i cannot see any thing on here.
its blank**
// recent products
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text('Recent products')),
),
],
),
Column(
children: productProvider.products
.map((item) => GestureDetector(
child: ProductCard(
product: item,
),
))
.toList(),
)
],
),
),
);
}
}
#FEATURED PRODUCT: this is linked to ProductProvider which listens from the
database
import 'package:farmers_ecommerce/provider/product.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'featured_card.dart';
class FeaturedProducts extends StatefulWidget {
#override
_FeaturedProductsState createState() => _FeaturedProductsState();
}
class _FeaturedProductsState extends State<FeaturedProducts> {
#override
Widget build(BuildContext context) {
final productProvider = Provider.of<ProductProvider>(context);
return Container(
height: 230,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: productProvider.products.length,
itemBuilder: (_, index) {
return FeaturedCard(
product: productProvider.products[index],
);
}));
}
}
#PRODUCT PROVIDER
//i feel the provider is not loading any products
import 'package:farmers_ecommerce/db/product.dart';
import 'package:farmers_ecommerce/models/product.dart';
import 'package:flutter/material.dart';
class ProductProvider with ChangeNotifier{
ProductServices _productServices = ProductServices();
List<ProductModel> products = [];
List<ProductModel> productsSearched = [];
ProductProvider.initialize(){
loadProducts();
}
loadProducts()async{enter code here
products = await _productServices.getProducts();
notifyListeners();
}
Future search({String productName})async{
productsSearched = await _productServices.searchProducts(productName: productName);
notifyListeners();
}
}
//DATABASE TO FIRESTORE
//I tried using stream builder but it is not working using Future.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:farmers_ecommerce/models/product.dart';
class ProductServices {
String collection = "products";
FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List<ProductModel>> getProducts() async =>
_firestore.collection(collection).get().then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.docs) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
Future<List<ProductModel>> searchProducts({String productName}) {
// code to convert the first character to uppercase
String searchKey = productName[0].toUpperCase() + productName.substring(1);
return _firestore
.collection(collection). //return fire base
.orderBy("name")
.startAt([searchKey])
.endAt([searchKey + '\uf8ff'])
.get()
.then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.docs) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
}
}

In your ProductServices change this function:
Future<List<ProductModel>> getProducts() async {
QuerySnapshot result= await _firestore.collection(collection).get();
List<ProductModel> products = [];
for (DocumentSnapshot product in result.docs) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
}
If you use then the return will be called when the code flow already left the function. To avoid that you need to await the result.

Related

I am unable to navigate to detail page from List Tile Page and show retrieved data of the particular item

I have uploaded few text items, image items and pdf documents to firebase database / storage and and able to retrieve all of them in HomeScreen i.e Vertical CardsUI list as well as ListTiles View with one image, one title and one subtitle.
But unable to build DetailView i.e One Singe Item's details instead of multipleCards and navigate to DetailView page
on click on any List Tile Item .
My code for HomeScreen.dart is as follows
import 'dart:async';
import 'dart:io';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:gadjet_inventory/Form/ListTileFeed.dart';
import 'package:gadjet_inventory/Form/ListTiles.dart';
import 'package:gadjet_inventory/Form/RetrievePage.dart';
import 'package:gadjet_inventory/main.dart';
import 'package:intl/intl.dart';
import 'package:gadjet_inventory/Form/Data.dart';
import 'UploadData.dart';
import 'package:pdf_flutter/pdf_flutter.dart';
// ignore: must_be_immutable
import 'package:url_launcher/url_launcher.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<Data> dataList = [];
List<bool> favList = [];
bool searchState = false;
FirebaseAuth auth = FirebaseAuth.instance;
String get data => null;
#override
void initState() {
// TODO: implement initState
super.initState();
DatabaseReference referenceData = FirebaseDatabase.instance.reference().child("Data");
referenceData.once().then((DataSnapshot dataSnapShot) {
dataList.clear();
favList.clear();
var keys = dataSnapShot.value.keys;
var values = dataSnapShot.value;
for (var key in keys) {
Data data = new Data(
values [key]['imgUrl'],
values [key]['wcimgUrl'],
values [key]['wcpdfUrl'],
values [key]['cattegorrytype'],
values [key]['companyname'],
values [key]['modelname'],
values [key]['seriesname'],
values [key]['serielnumber'],
key
//key is the uploadid
);
dataList.add(data);
auth.currentUser().then((value) {
DatabaseReference reference = FirebaseDatabase.instance.reference().child("Data").child(key).child("Fav")
.child(value.uid).child("state");
reference.once().then((DataSnapshot snapShot){
if(snapShot.value!=null){
if(snapShot.value=="true"){
favList.add(true);
}else{
favList.add(false);
}
}else{
favList.add(false);
}
});
});
}
Timer(Duration(seconds: 1),(){
setState(() {
//
});
});
});
}
int selectedRadioTile;
String get path => null;
String get title => null;
setSelectedRadioTile(int val) {
setState(() {
selectedRadioTile = val;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.lightGreen,
//Color(0xffffffff),
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.blue,
title: new Text("Device Details", style:
TextStyle(fontSize: 20), textAlign: TextAlign.center),
),
body: dataList.length == 0
? Center(
child: Text("No Data Available", style: TextStyle(fontSize: 30),))
: ListView.builder(
itemCount: dataList.length,
itemBuilder: (_, index) {
return CardUI(dataList[index].imgUrl,dataList[index].wcimgUrl, ,dataList[index].wcpdfUrl, dataList[index].cattegorrytype,
dataList[index].companyname, dataList[index].modelname,dataList[index].seriesname, dataList[index].uploadid,index);
}
),
);
}
Widget CardUI(String imgUrl, String wcimgUrl, String wcpdfUrl, String cattegorrytype, String companyname, String modelname,
String seriesname String uploadId,int index) {
return Card(
elevation: 7,
margin: EdgeInsets.all(15),
//color: Color(0xffff2fc3),
color:Colors.blueGrey,
child: Container(
color: Colors.white,
margin: EdgeInsets.all(1.5),
padding: EdgeInsets.all(10),
child: Column(
children: <Widget>[
Image.network(
imgUrl != null
? imgUrl
: '',
width: 500,
height: 500,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text( "Cattegorry Type:- "
"$cattegorrytype",
style: TextStyle(color: Colors.black),
),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Theme(
data: ThemeData(
hintColor: Colors.blue,
),
child: Text( "Company Name:- "
"$companyname",
style: TextStyle(color: Colors.black),
),
),
),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Theme(
data: ThemeData(
hintColor: Colors.blue,
),
child: Text( "Model Name:- "
"$modelname",
style: TextStyle(color: Colors.black),
),
),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Theme(
data: ThemeData(
hintColor: Colors.blue,
),
child: Text( "Series Name:- "
"$seriesname",
style: TextStyle(color: Colors.black),
),
),
),
),
],
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.blue,
child: Text("Warranty Card",
style: TextStyle(fontSize: 18, color: Colors.white),),
),
RadioListTile(
value: 1,
groupValue: selectedRadioTile,
title: Text("PDF"),
//subtitle: Text("Upload PDF File"),
/* onChanged: (val) {
filePicker(context);
},*/
activeColor: Colors.red,
),
Padding(padding: EdgeInsets.only(top: 15)),
// _buildPDF1Field(context),
PDF.network(
wcpdfUrl != null
? wcpdfUrl
: '',
width: 600,
height: 1000, placeHolder: Image.asset("assets/images/pdf.png",
height: 600, width: 500),
),
SizedBox(height: 24),
RadioListTile(
value: 2,
groupValue: selectedRadioTile,
title: Text("Image"),
//subtitle: Text("Upload W Card Image"),
/* onChanged: (val) {
openWCImagePickerModal(context);
//_startWCUpload();
},*/
activeColor: Colors.blue,
),
Padding(padding: EdgeInsets.only(top: 15)),
Image.network(
wcimgUrl != null
? wcimgUrl
: 'https://www.testingxperts.com/wp-content/uploads/2019/02/placeholder-img.jpg',
width: 500,
height: 500,
),
SizedBox(height: 24),
],
),
),
);
}
}.
Now my requirement is to show Detail View of single item when clciked on it in ListTiles , it should navigate to DetailPage and show me the details of that particular item.
How to build DetailView page ? and Navigate from ListTilePage
I have achieved this using seperate DetailView.dart page.
I have created DetailView.dart page separately like
class DetailView extends StatefulWidget {
#override
_DetailViewState createState() => _DetailViewState();
}
class _DetailViewState extends State<DetailView> {
List<Data> dataList = [];
List<bool> favList = [];
bool searchState = false;
FirebaseAuth auth = FirebaseAuth.instance;
String get data => null;
} etc

Want to pass the total price in the bottom navigation bar in flutter

How can i show the total amount in the bottom navigation bar... The app uses firebase backend... I have a filed in my database name total price of each item... Now I want to fetch the total price of each item and then add it and display in the bottom navigation bar..
I have attach my firebase backend screen shot.. what i need is to get all the value of the field 'total' add it up and show it in the bottom bar below the Total which is hardcoded as 999 currently section...
It would be helpful if some let me know how to do it.. I am new to app development and flutter as well
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'package:fluttertoast/fluttertoast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final myController = TextEditingController(); ///Alert Dialog box input text myController will be use to store the number of qty
String id;
var qty;
var price;
var total;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home:Scaffold(
bottomNavigationBar: new Container( //// Bottom Naviagtion Bar for check out and Total price
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(child: ListTile(
title: Text("Total"),
subtitle: Text("Rs 999"),
),),
Expanded(
child: MaterialButton(onPressed:() {},
child: Text("Check Out",style: TextStyle(color: Colors.white),),
color: Colors.red,) ,
)
],
),
),
appBar: AppBar(title: Text('MyKart'),
),
body: (
StreamBuilder(
stream: Firestore.instance.collection('KartDetails').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot kartDetails = snapshot.data.documents[index];
return Container(
height: 150,
child: Card(
elevation: 10,
child: Container(
height: 100,
width: 100,
child: Row(
children: <Widget>[
Container(
width: 100,
height: 100,
child: Image.network(kartDetails['img']),
),
Container(
child: (Text(kartDetails['item'])),
),
Container(
width: 50,
child: (Text('Rs '+kartDetails['price'].toString(),textAlign: TextAlign.end,)),
),
Container(
margin: EdgeInsets.only(left: 20),
height: 120,
width: 50,
color: Colors.white10,
child: Column(
children: <Widget>[
RaisedButton(
color: Colors.grey,
onPressed: (){
showDialog(context: context,
builder: (BuildContext context){
return Dialog(
child: Container(
height: 250,
color: Colors.white10,
child: Container(
margin: EdgeInsets.all(40.0),
child: Column(
children: <Widget>[
TextField(
controller: myController,
keyboardType: TextInputType.number,
decoration: InputDecoration(hintText: 'Enter the Quantity'),
),
Container(
height: 50,
),
RaisedButton(
color: Colors.blue,
child: Text('Submit'),
onPressed: () async{
qty = myController.text;
//==================================================================Total Number of QTY ENTERED==========================================//
if (int.parse(qty)>0 && int.parse(qty)>=5) {
CollectionReference collectionRefernce = Firestore
.instance.collection(
'KartDetails');
QuerySnapshot querySnapshot = await collectionRefernce
.getDocuments();
querySnapshot
.documents[index]
.reference
.updateData(
{"quantity": qty});
//==================================================================Calculate price for each product==========================================//
price = kartDetails['price'];
total=int.parse(qty)*price;
querySnapshot
.documents[index]
.reference
.updateData(
{"total": total});
print(myController
.toString());
Navigator.of(context)
.pop();
myController.clear();
Fluttertoast.showToast(msg: "Quantity Updated",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
}
else if(int.parse(qty) < 5 || int.parse(qty)<0) {
Fluttertoast.showToast(msg: "Minimum 5 quanity",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
myController.clear();
}
else {
Fluttertoast.showToast(msg: "Please enter valid quantity",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 20.0
);
myController.clear();
}
//Firebase query
},
)
],
),
),
),
);
});
},
child: Icon(Icons.shopping_basket),
),
Container(
height: 20,
),
RaisedButton(
color: Colors.grey,
child: Icon(Icons.delete,color: Colors.black87,),
)
],
),
),
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 3),
height: 50,
width: 70,
child: Center(child: Text('Quantity')),
),
Container(
width: 70,
child: Center(child: Text((kartDetails['quantity']).toString())),
),
Container(
margin: EdgeInsets.only(top: 25),
child: Center(child: Text('Total Price')),),
Container(
margin: EdgeInsets.only(left: 3),
width: 70,
child: Center(child: Text(("Rs " + (kartDetails['total']).toString()))),
),
],
),
],
),
),
),
);
},
);
}
else{
return Center(
child: Container(),
);;
}
},
)
),
),
);
}
}
You can easily do it with this method:
var totalCartValue = 0;
String getCartTotal() async {
QuerySnapshot snapshot = await Firestore.instance
.collection('KartDetails')
.getDocuments();
snapshot.documents.forEach((doc) {
setState((){
totalCartValue += doc.data['total'];
});
});
return totalCartValue.toString();
}
P.S: This method will give you the total of all values in the KartDetails collection not the total for the current user, for the current user it should be like this:
var totalCartValue = 0;
String getCartTotal() async {
QuerySnapshot snapshot = await Firestore.instance
.collection('KartDetails')
.where("UID", isEqualTo: FirebaseAuth.instance.currentUser().toString())
.getDocuments();
snapshot.documents.forEach((doc) {
setState((){
totalCartValue += doc.data['total'];
});
});
return totalCartValue.toString();
}
And use it in the UI that way:
class YourClassName extends StatefulWidget {
#override
_YourClassNameState createState() => _YourClassNameState();
}
class _YourClassNameState extends State<YourClassName> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: //your body code,
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.cart_shopping),
title: new Text(totalCartValue),
),
]
)
);
}
}
You should call it inside your initState so it gets executed whenever app starts:
#override
initState(){
super.initState();
getCartTotal();
}
This is a very vague question, so I will give a shot at one method of solving this. In order to do this you will need some sort of state management solution. I suggest using provider. Flutter has a tutorial on provider here. Essentially you will have to create a ChangeNotifier that every time would onAddItem and onDeleteItem and call notifyListeners() whenever you add or delete items. Then your bottom bar would simply use a Consumer to get the values from your ChangeNotifier. As I said this is just one approach, but since you did not give a replicable example this is the best I can do.

How to store geolocation data in Flutter with Cloud Firestore

I have a problem querying my geolocation data from my database in Cloud Firestore. I went through the documentation on Youtube and came to the conclusion that it will work best for me when i save the geolocation data in subcollections.
Here is my databse structure:
And if you go into one of the documents in the subcollection:
The database itself has a collection called "tourguides", with each document containing basic info like the name of the tour and the region where the tour is (both are Strings). Each of the documents then have a subcollection called "locations", where each document has the Strings "Name" and "ID" and also a geopoint with latitude and longitude data.
The documents from the "Tourguides" collection are shown in a ListView. Whenever i tap on one of the entries, a map shall open where all the markers from the respective subcollection are shown.
Here is my ListView Builder:
#override
void initState() {
super.initState();
_pointsofinterest = Firestore.instance.collection('tourguides').document('sydney_downtown_guide').col lection('locations').orderBy('name').snapshots();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
stream: _pointsofinterest,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text('Loading...');
default:
return new ListView(
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return InkWell(
child: new ListTile(
title: new Text(document['name']),
subtitle: new Text(document['region']),
onTap: () {
return TourMap(
documents: snapshot.data.documents,
initialPosition: const LatLng(-33.868210, 151.208391),
mapController: _mapController,
);
},
),
);
}).toList(),
);
}
},
),
);
}
I put my map into a StatlessWidget (I am not sure. Maybe this has to be a StatefulWidget?):
class TourMap extends StatelessWidget {
const TourMap({
Key key,
#required this.documents,
#required this.initialPosition,
#required this.mapController,
}) : super(key: key);
final List<DocumentSnapshot> documents;
final LatLng initialPosition;
final Completer<GoogleMapController> mapController;
#override
Widget build(BuildContext context) {
return GoogleMap(
initialCameraPosition: CameraPosition(
target: initialPosition,
zoom: 12,
),
markers: documents
.map((document) => Marker(
markerId: MarkerId(document['placeId']),
icon: BitmapDescriptor.defaultMarker,
position: LatLng(
document['geolocation'].latitude,
document['geolocation'].longitude,
),
infoWindow: InfoWindow(
title: document['location_name'],
),
))
.toSet(),
onMapCreated: (mapController) {
this.mapController.complete(mapController);
},
);
}}
Now i dont exactly know how to set up the query in my OnTap function. The Firestore documentation showed that i always have to refer to specfic documents if i go down the collections from my database.
For example (collection/document/collecion). But in my query, the "document" in the middle of the path is always different, depending on which tourguide the user clicks.
Any ideas on that? Looking Forward to your replies!
UPDATE: I slightly configured my database structure! I now use two seperate databases. One database holds information about the available tourguides (just two Strings currently: Name and Region) and the other stores the actual individual Locations.
I now use where-queries to get the correct locations based on the tourguide´s Name they´re belonging to.
The query itself works on the OnTap function now:
return new ListView(
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return InkWell(
child: new ListTile(
title: new Text(document['name']),
subtitle: new Text(document['region']),
onTap: () {
Firestore.instance.collection('locations').where(
"toActivity",
isEqualTo: document['name'],
)
.snapshots()
.listen((data) =>
data.documents.forEach((doc) => print(doc["location_name"])));
},
),
);
}).toList(),
);
The database structure:
The correct entries are printed into the console if i tap on one of the entries in the ListView. But i will need a Google Map to pop up that shows the appropriate markers based on the "geolocation" values from the database.
Bro, I did. I can retrieve it by two ways.
1. manually by using simple 'initState'.
2. second by using provider (but by using the second method, i have not succeed to show the marker, yet). Hope can help you, although it was long time ago. Here is mine by using 'initState':
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:visitmalang/provider/aktivitas_provider.dart';
import 'package:visitmalang/ui/home/beranda/aktivitas/profil_agen_wisata.dart';
import 'package:visitmalang/ui/widget/textcustom.dart';
class MapAktivitas extends StatefulWidget {
#override
_MapAktivitasState createState() => _MapAktivitasState();
}
class _MapAktivitasState extends State<MapAktivitas> {
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
GoogleMapController mapController;
bool mapToggle = false;
bool geraiToggle = false;
var currentLocation;
var clients = [];
#override
void initState() {
// TODO: implement initState
super.initState();
Geolocator().getCurrentPosition().then((lokasiSekarang) {
setState(() {
currentLocation = lokasiSekarang;
mapToggle = true;
populateClients();
});
});
}
populateClients() {
clients = [];
Firestore.instance.collection('trail').getDocuments().then((docs) {
if (docs.documents.isNotEmpty) {
setState(() {
geraiToggle = true;
});
for (int i = 0; i < docs.documents.length; i++) {
clients.add(docs.documents[i].data);
initMarker(docs.documents[i].data, docs.documents[i].documentID);
}
}
});
}
void initMarker(request, requestId) {
var markerIdVal = requestId;
final MarkerId markerId = MarkerId(markerIdVal);
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
request['koordinat'].latitude, request['koordinat'].longitude),
infoWindow: InfoWindow(title: request['nama']));
setState(() {
markers[markerId] = marker;
});
}
Widget clientCard(client) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: InkWell(
onTap: () {
zoomInMarker(client);
},
child: Stack(
alignment: FractionalOffset(0.5, 0.94),
children: <Widget>[
Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(10.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white,
),
height: 108,
width: 200,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0)),
child: Container(
width: 96,
height: 108,
child: Image.asset(
'assets/trail.png',
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 4,
),
Stack(
alignment: FractionalOffset(0.5, 0.9),
children: <Widget>[
Container(
width: 100,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0),
child: Container(
alignment: Alignment.center,
child: textCustom(client['nama'],
Colors.black87, 14, 'Montserrat'),
),
),
],
),
),
),
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: InkWell(
onTap: () => Navigator.of(context).push(
CupertinoPageRoute(
builder: (BuildContext context) =>
ProfilAgenWisata(
nama: client['nama'],
deskripsi: client['deskripsi'],
website: client['website'],
email: client['email'],
noTelepon: client['noTelepon'],
whatsApp: client['whatsApp'],
alamat: client['alamat'],
fasilitas: client['fasilitas'],
))),
child: Container(
alignment: Alignment.center,
color: Color(0xFFDB5C48),
height: 40,
width: 88,
child: textCustom(
'Detail', Colors.white, 14, 'Montserrat'),
),
),
)
],
),
],
),
),
),
],
)),
);
}
zoomInMarker(client) {
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
client['koordinat'].latitude, client['koordinat'].longitude),
zoom: 16.0,
bearing: 19.0,
tilt: 15.0),
),
);
}
#override
Widget build(BuildContext context) {
// AktivitasNotifier aktivitasNotifier = Provider.of<AktivitasNotifier>(context);
return Scaffold(
appBar: AppBar(
title: textCustom('Ngetrail', Colors.black87, 18, 'Montserrat'),
centerTitle: true,
elevation: 0.0,
backgroundColor: Colors.transparent.withOpacity(0.0),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black87),
onPressed: (){Navigator.pop(context);},),
),
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height - 80,
child: mapToggle
? GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
markers: Set<Marker>.of(markers.values),
compassEnabled: false,
zoomControlsEnabled: false,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 15),
onMapCreated: (controller) {
setState(() {
mapController = controller;
});
},
)
: Center(
child: textCustom(
'Loading...', Colors.black87, 20, 'Hind')),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 140.0,
width: MediaQuery.of(context).size.width,
child: geraiToggle
? ListView(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.all(8.0),
children: clients.map((element) {
return clientCard(element);
}).toList(),
)
: Container(),
),
SizedBox(
height: 56.0,
)
],
)
],
));
}
}
Here is the second method, by using provider.
First, you have to decide the model (just focus on 'koordinat'):
class ModelAktivitas {
String idAktivitas;
var koordinat;
String nama;
String deskripsi;
String alamat;
String email;
String noTelepon;
String website;
String gambarUtama;
List galeri;
List fasilitas;
ModelAktivitas.fromMap(Map<String, dynamic> data) {
idAktivitas = data['idAktivitas'];
koordinat = data['koordinat'];
nama = data['nama'];
deskripsi = data['deskripsi'];
noTelepon = data['nomorTelepon'];
galeri = data['galeri'];
fasilitas = data['fasilitas'];
alamat = data['alamat'];
email = data['alamat'];
gambarUtama = data['gambarUtama'];
website = data['website'];
}
}
second, make provider for it:
import 'dart:collection';
import 'package:flutter/cupertino.dart';
import 'package:visitmalang/models/aktivitas_model.dart';
class AktivitasNotifier with ChangeNotifier {
List<ModelAktivitas> _listAktivitas = [];
ModelAktivitas _detailAktivitas;
UnmodifiableListView<ModelAktivitas> get listAktivitas =>
UnmodifiableListView(_listAktivitas);
ModelAktivitas get detailAktivitas => _detailAktivitas;
set listAktivitas(List<ModelAktivitas> listAktivitas) {
_listAktivitas = listAktivitas;
notifyListeners();
}
set detailAktivitas(ModelAktivitas aktivitas) {
_detailAktivitas = aktivitas;
notifyListeners();
}
}
After that, add the "get" from your firestore services:
getListAktivitas(AktivitasNotifier aktivitasNotifier) async {
QuerySnapshot snapshot =
await Firestore.instance.collection('trail').getDocuments();
List<ModelAktivitas> _listAktivitas = [];
snapshot.documents.forEach((doc) {
ModelAktivitas modelAktivitas = ModelAktivitas.fromMap(doc.data);
_listAktivitas.add(modelAktivitas);
});
aktivitasNotifier.listAktivitas = _listAktivitas;
}
then, the last step stream it to your UI code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:visitmalang/provider/aktivitas_provider.dart';
import 'package:visitmalang/ui/home/beranda/aktivitas/profil_agen_wisata.dart';
import 'package:visitmalang/ui/widget/textcustom.dart';
import 'package:visitmalang/service/user_service.dart';
class MapAktivitasTandingan extends StatefulWidget {
#override
_MapAktivitasTandinganState createState() => _MapAktivitasTandinganState();
}
class _MapAktivitasTandinganState extends State<MapAktivitasTandingan> {
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
GoogleMapController mapController;
bool mapToggle = false;
bool geraiToggle = false;
var currentLocation;
#override
void initState() {
// TODO: implement initState
super.initState();
Geolocator().getCurrentPosition().then((lokasiSekarang) {
setState(() {
currentLocation = lokasiSekarang;
mapToggle = true;
});
});
AktivitasNotifier aktivitasNotifier =
Provider.of<AktivitasNotifier>(context, listen: false);
getListAktivitas(aktivitasNotifier);
}
#override
Widget build(BuildContext context) {
AktivitasNotifier aktivitasNotifier =
Provider.of<AktivitasNotifier>(context);
return Scaffold(
appBar: AppBar(
title: textCustom('Ngetrail', Colors.black87, 18, 'Montserrat'),
centerTitle: true,
elevation: 0.0,
backgroundColor: Colors.transparent.withOpacity(0.0),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black87),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height - 80,
child: mapToggle
? GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
markers: {
},
compassEnabled: false,
zoomControlsEnabled: false,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 15),
onMapCreated: (controller) {
setState(() {
mapController = controller;
});
},
)
: Center(
child: textCustom(
'Loading...', Colors.black87, 20, 'Hind')),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 140.0,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: aktivitasNotifier.listAktivitas.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: InkWell(
onTap: () {
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
aktivitasNotifier
.listAktivitas[index]
.koordinat
.latitude,
aktivitasNotifier
.listAktivitas[index]
.koordinat
.longitude),
zoom: 16.0,
bearing: 19.0,
tilt: 15.0),
),
);
},
child: Stack(
alignment: FractionalOffset(0.5, 0.94),
children: <Widget>[
Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(10.0),
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10.0),
color: Colors.white,
),
height: 108,
width: 200,
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
//
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft:
Radius.circular(10.0)),
child: Container(
width: 96,
height: 108,
child: Image.asset(
'assets/trail.png',
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 4,
),
Stack(
alignment:
FractionalOffset(0.5, 0.9),
children: <Widget>[
Container(
width: 100,
child: Padding(
padding:
const EdgeInsets.only(
top: 8.0),
child: Column(
children: <Widget>[
Padding(
padding:
const EdgeInsets
.symmetric(
horizontal:
8.0),
child: Container(
alignment:
Alignment.center,
child: textCustom(
aktivitasNotifier
.listAktivitas[
index]
.nama,
Colors.black87,
14,
'Montserrat'),
),
),
],
),
),
),
ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: InkWell(
onTap: () => Navigator.of(
context)
.push(CupertinoPageRoute(
builder: (BuildContext
context) =>
ProfilAgenWisata(
nama: aktivitasNotifier
.listAktivitas[
index]
.nama,
website: aktivitasNotifier
.listAktivitas[
index]
.website,
noTelepon: aktivitasNotifier
.listAktivitas[
index]
.noTelepon,
email: aktivitasNotifier
.listAktivitas[
index]
.email,
alamat: aktivitasNotifier
.listAktivitas[
index]
.alamat,
deskripsi: aktivitasNotifier
.listAktivitas[
index]
.deskripsi,
))),
child: Container(
alignment: Alignment.center,
color: Color(0xFFDB5C48),
height: 40,
width: 88,
child: textCustom(
'Detail',
Colors.white,
14,
'Montserrat'),
),
),
)
],
),
],
),
),
),
],
)),
);
},
)),
SizedBox(
height: 56.0,
)
],
)
],
));
}
}

How to get array data back to mobile screen from firebase (Flutter)

How to get back array data to the mobile screen.
The String in the firebase is retrieved easily but I have problem with array data.
1) main.dart :
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'firestoreservice.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'taskscreen.dart';
import 'task.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ToDo APP',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color(0xff543B7A),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Task> items;
FirestoreService fireServ = new FirestoreService();
StreamSubscription<QuerySnapshot> todoTasks;
#override
void initState() {
super.initState();
items=new List();
todoTasks?.cancel();
todoTasks=fireServ.getTaskList().listen((QuerySnapshot snapshot){
final List<Task> tasks=snapshot.documents
.map((documentSnapshot) => Task. fromMap(documentSnapshot.data))
.toList();
setState(() {
this.items = tasks;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: <Widget>[
_myAppBar(context),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 80,
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Stack(children: <Widget>[
// The containers in the background
Column(children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 80.0,
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Material(
color: Colors.white,
elevation: 14.0,
shadowColor: Color(0x802196F3),
child: Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${items[index].name}',
style: TextStyle(
color: Colors.black,
fontSize: 20.0),
),
Text(
'${items[index].size}',
style: TextStyle(
color: Colors.black,
fontSize: 20.0),
),
Container(
child: Image.network(
'${items[index].imageU}',
)),
],
),
),
),
),
),
),
),
]),
]);
}),
),
],
),
);
}
Widget todoType(String icontype) {
IconData iconval;
Color colorval;
switch (icontype) {
case 'travel':
iconval = FontAwesomeIcons.mapMarkerAlt;
colorval = Color(0xff4158ba);
break;
case 'shopping':
iconval = FontAwesomeIcons.shoppingCart;
colorval = Color(0xfffb537f);
break;
case 'gym':
iconval = FontAwesomeIcons.dumbbell;
colorval = Color(0xff4caf50);
break;
case 'party':
iconval = FontAwesomeIcons.glassCheers;
colorval = Color(0xff9962d0);
break;
default:
iconval = FontAwesomeIcons.tasks;
colorval = Color(0xff0dc8f5);
//
}
return CircleAvatar(
backgroundColor: colorval,
child: Icon(iconval, color: Colors.white, size: 20.0),
);
}
Widget _myAppBar(context) {
return Container(
height: 80.0,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color(0xFFFA7397),
const Color(0xFFFDDE42),
],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 0.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: const EdgeInsets.only(top: 16.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 5,
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'ToDo Tasks',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
),
),
Expanded(
flex: 1,
child: Container(
child: IconButton(
icon: Icon(
FontAwesomeIcons.search,
color: Colors.white,
),
onPressed: () {
//
}),
),
),
],
)),
),
);
}
}
2) task.dart
class Task{
String _name;
String _size;
Task(this._name ,this._size);
Task.map(dynamic obj){
this._name = obj['name'];
this._size=obj['size'];
List<String> imageU= new List<String>();
}
String get name=> _name;
String get size=>_size;
Task.fromMap(Map<String,dynamic> map){
this._name = map['name'];
this._size= map['size'];
this.imageU= List.from(map['images']);
}
}
3) firestoreservice.dart
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'task.dart';
final CollectionReference myCollection =
Firestore.instance.collection('products');
class FirestoreService {
Future<Task> createTODOTask(String name, String size) async {
final TransactionHandler createTransaction = (Transaction tx) async {
final DocumentSnapshot ds = await tx.get(myCollection.document());
};
return Firestore.instance.runTransaction(createTransaction).then((mapData) {
return Task.fromMap(mapData);
}).catchError((error) {
print('error: $error');
return null;
});
}
Stream<QuerySnapshot> getTaskList({int offset, int limit}) {
Stream<QuerySnapshot> snapshots = myCollection.snapshots();
if (offset != null) {
snapshots = snapshots.skip(offset);
}
if (limit != null) {
snapshots = snapshots.take(limit);
}
return snapshots;
}
}
How to get back array data to the mobile screen. The String in the firebase is retrieved easily but I have a problem with array data.
Convert task.dart to see what solution will work:
class Task{
String name;
List<String> size= new List<String>();
Task.fromMap(Map<String,dynamic> map){
this.name = map['name'];
this.size= List.from(map['size' ]);
}
}
And make sure all the documents in the image have "size" field.

error:- Another exception was thrown: A RenderFlex overflowed by 33 pixels on the bottom

[enter image description here]
1Error showing when i run my app...My code is below ...can anyone tell what is wrong with my code
///////////////////////
Error showing when i run my app...My code is below ...can anyone tell what is wrong with my code
///////////////////////
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
import
'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
class OfferPage extends StatefulWidget {
#override
_OfferPageState createState() => new _OfferPageState();
}
class _OfferPageState extends State<OfferPage> {
StreamSubscription<QuerySnapshot> subscription;
List<DocumentSnapshot> offerpostList;
final CollectionReference collectionReference =
Firestore.instance.collection("todos");
#override
void initState() {
// TODO: implement initState
super.initState();
subscription = collectionReference.snapshots().listen((datasnapshot) {
setState(() {
offerpostList = datasnapshot.documents;
});
});
// _currentScreen();
}
#override
void dispose() {
subscription?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: offerpostList != null? new StaggeredGridView.countBuilder(
padding: const EdgeInsets.all(8.0),
crossAxisCount: 4,
itemCount: offerpostList.length,
itemBuilder: (context, i) {
String imgPath = offerpostList[i].data['url'];
String title = offerpostList[i].data['productTitle'];
return new Material(
elevation: 8.0,
borderRadius:
new BorderRadius.all(new Radius.circular(8.0)),
child: new InkWell(
child:new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(title,style: new TextStyle(
fontStyle: FontStyle.italic,
color: Colors.green[900],
fontSize: 16.0)),
new Hero(
tag: imgPath,
child:
new FadeInImage(
image: new NetworkImage(imgPath),
fit: BoxFit.cover,
placeholder: new AssetImage("assets/logo.png"),
),
),
],
),
),
);
},
staggeredTileBuilder: (i) =>
new StaggeredTile.count(2, i.isEven ? 2 : 3),
mainAxisSpacing: 8.0,
crossAxisSpacing: 8.0,
)
: new Center(
child: new CircularProgressIndicator(),
));
}
}
Column in flutter doesn't have scrolling ability. The issue is your data from firebase cannot be fit inside a single screen. That's why overflow error was thrown. Use ListView instead of Column which has the scrolling ability.
Column widget for available room in the device to get qll data in firebase and also to get scroll effect you can use FirebaseAnimatedList.
For an Olx like gridview with text over image, here is a sample. Try it out and change your question because it might be misleading.
main.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firestore_grid_view/product.dart';
import 'package:firestore_grid_view/product_details.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new MyApp(),
debugShowCheckedModeBanner: false,
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Product> _products = [];
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Home'),
),
body: new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('products').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new GridView.count(
crossAxisCount: 2,
children: _buildGrid(snapshot.data.documents),
);
},
),
);
}
List<Widget> _buildGrid(List<DocumentSnapshot> documents) {
List<Widget> _gridItems = [];
_products.clear();
for (DocumentSnapshot document in documents) {
_products.add(new Product(
name: document['productTitle'],
category: document['category'],
imageUrl: document['url'],
contactNumber: document['contactNumber']));
}
for (Product product in _products) {
_gridItems.add(_buildGridItem(product));
}
return _gridItems;
}
Widget _buildGridItem(Product product) {
return new GestureDetector(
child: new Card(
child: new Stack(
alignment: Alignment.center,
children: <Widget>[
new Hero(
tag: product.name,
child: new Image.network(product.imageUrl, fit: BoxFit.cover),
),
new Align(
child: new Container(
padding: const EdgeInsets.all(10.0),
child: new Text(product.name,
style: new TextStyle(color: Colors.white)),
color: Colors.black.withOpacity(0.4),
width: double.infinity,
),
alignment: Alignment.bottomCenter,
),
],
),
),
onTap: () => onProductTapped(product),
);
}
onProductTapped(Product product) {
Navigator.of(context).push(new MaterialPageRoute(
builder: (context) => new ProductDetails(product)));
}
}
product_details.dart
import 'package:firestore_grid_view/product.dart';
import 'package:flutter/material.dart';
class ProductDetails extends StatelessWidget {
final Product product;
ProductDetails(this.product);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
children: <Widget>[
new Expanded(child: new Container()),
new Hero(
tag: product.name,
child: new Image(
image: new NetworkImage(product.imageUrl),
fit: BoxFit.fill,
width: double.infinity,
height: 300.0,
)),
new Padding(
padding: const EdgeInsets.all(15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(right: 8.0),
child: new Text(
'Category -',
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
new Text(
product.category,
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
],
),
),
new Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(right: 8.0),
child: new Text(
'Contact Number -',
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
new Text(
product.contactNumber,
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
],
),
),
new Expanded(child: new Container()),
],
),
);
}
}
product.dart
class Product {
final name, category, imageUrl, contactNumber;
Product({this.name, this.category, this.imageUrl, this.contactNumber});
}

Resources