Related
#override
Widget build(BuildContext context) {
return InkWell(
onTap: ()
{
Navigator.push(context, MaterialPageRoute(builder: (c)=> HistoryDetailScreen(orderID: orderID)));
},
child: FutureBuilder<DocumentSnapshot>(
future: FirebaseFirestore.instance
.collection("orders")
.doc(orderID)
.get(),
builder: (c, snapshot)
{
Map? dataMap;
if(snapshot.hasData)
{
dataMap = snapshot.data!.data()! as Map<String, dynamic>;
totalAmount = dataMap["totalAmount"].toString();
customerName = dataMap["orderBy"].toString();
}
return snapshot.hasData
?
Container(
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 5,),
Text(
"ORDER ID: "+customerName.toString(),
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontFamily: "Acme",
),
),
SizedBox(height: 5),
Text(
"Total Amount: ₱" + totalAmount.toString(),
style: const TextStyle(
fontWeight: FontWeight.w500,
color: Colors.black,
fontSize: 16,
fontFamily: "Acme",
),
),
SizedBox(height: 5,),
Text(
"More Info >>",
style: const TextStyle(
color: Colors.grey,
fontSize: 13,
fontFamily: "Acme",
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white
),
padding: const EdgeInsets.all(5),
margin: const EdgeInsets.all(5),
height: itemCount! * 50,
child: Stack(
children: [
Padding(padding: EdgeInsets.all(10)),
ListView.builder(
itemCount: itemCount,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index)
{
Items model = Items.fromJson(data![index].data()! as Map<String, dynamic>);
return Align(
heightFactor: 0.3,
alignment: Alignment.topCenter,
child: placedOrderDesignWidget(model, context, seperateQuantitiesList![index]),
);
},
),
],
),
),
],
),
)
:Center(child: circularProgress(),);
},
),
);
}
}
Widget placedOrderDesignWidget(Items model, BuildContext context, seperateQuantitiesList)
{
return Container(
width: MediaQuery.of(context).size.width,
height: 110,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 3,
blurRadius: 3,
offset: Offset(0, 3), // changes position of shadow
),
],
),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.0), //add border radius
child: Image.network(model.thumbnailUrl!, width: 90, height: 90, fit: BoxFit.cover,),
),
const SizedBox(width: 10.0,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Text(
model.name! + " x " + seperateQuantitiesList,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontFamily: "Acme",
),
),
),
const SizedBox(
width: 5,
),
],
),
Text(
"₱ " + model.price.toString(),
style: TextStyle(fontSize: 16.0, color: Colors.blue),
),
],
),
),
],
),
),
);
}
I wanted to avoid the overlapping of data that being shown in my screen
i have a firestore collection named 'orders'. It has user details as field name 'uid'. The field 'uid' is a reference to user data present in 'users' collections. No i have to display username along with order details. So i need to get data from the reference field. i'm using Streambuilder to display data. Here is what i did:
Widget build(BuildContext context) {
Map UserSnapshot = Map();
return Scaffold(
body: StreamBuilder(
stream:_db.collection('users').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> UsersSnapshot) {
UsersSnapshot.data?.docs.forEach((element) {
UserSnapshot[element.id] = element;
});
return StreamBuilder(
stream:_db.collection('orders').where(
'driverId', isEqualTo: sp.getString('uid')).snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> OrdersSnapshot) {
if (!OrdersSnapshot.hasData) return const Text('Loading...');
return ListView.builder(
itemCount: OrdersSnapshot.data!.docs.length,
itemBuilder:(context,index) {
var documentSnapshot= OrdersSnapshot.data!.docs[index].data() as Map<String,dynamic>;
return Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Container(
width: MediaQuery.of(context).size.width,
height: 260,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.black38, width: 1)),
child: Column(
children: [
Row(
children: [
Padding(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
child: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
border: Border.all(color: Colors.black12)),
child: Image.network(
'https://indiaeducationdiary.in/wp-content/uploads/2020/10/IMG-20201024-WA0014.jpg')),
),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Paradise Multicuisine Restaurant',
style: GoogleFonts.poppins(
fontWeight: FontWeight.bold, fontSize: 14),
overflow: TextOverflow.ellipsis,
),
Text(
'372,Kamarajar Salai, Karaikal',
style: GoogleFonts.poppins(
fontWeight: FontWeight.w400,
fontSize: 11,
color: hexStringToColor('636567')),
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
DottedLine(
dashColor: Colors.black26,
dashGapLength: 10,
),
Padding(
padding: EdgeInsets.all(20),
child: Container(
width: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.account_circle),
SizedBox(
width: 7,
),
Text(
UserSnapshot[documentSnapshot['uid']['fullname']] ?? 'Deleted User',
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: hexStringToColor('636567')),
),
SizedBox(width: 3),
Text(
'#'+ documentSnapshot['orderId'],
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: hexStringToColor('636567')),
)
],
),
Container(
width: MediaQuery.of(context).size.width * 0.90,
child: Row(
children: [
Icon(Icons.location_on_rounded),
SizedBox(
width: 7,
),
Expanded(
child: Text(
'6/8, RR Colony, Ambedkar Street, Karaikal',
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: hexStringToColor('636567')),
overflow: TextOverflow.clip,
maxLines: 4,
),
),
],
),
),
SizedBox(height: 20,),
Row(
children: [
Container(
decoration: BoxDecoration(
color: hexStringToColor('aeaeae'),
borderRadius: BorderRadius.circular(5)
),
width: 80,
height: 20,
child: Row (
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('3 Items',
style: GoogleFonts.poppins(fontSize: 10, fontWeight: FontWeight.w500),
)
],
),
),
SizedBox(width: 20,),
Container(
decoration: BoxDecoration(
color: hexStringToColor('aeaeae'),
borderRadius: BorderRadius.circular(5)
),
width: 80,
height: 20,
child: Row (
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("₹"+documentSnapshot['grandTotal'].toString(),
style: GoogleFonts.poppins(fontSize: 10, fontWeight: FontWeight.w500),
)
],
),
),
],
),
Align(
child: ElevatedButton(onPressed: ()=>{},
child: Text('View Details'),
style: ElevatedButton.styleFrom(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5)
),
textStyle: GoogleFonts.poppins(fontWeight: FontWeight.w400,fontSize: 14)
),
),
alignment: Alignment.centerRight,
)
],
),
),
)
],
),
),
);
}
);
}
);
},
)
);
}}
You can iterate over the snapshots using asyncMap.
For example:
stream:_db.collection('users').snapshots().asyncMap((event) async {
event.docs.map((userDoc) {
var userData = userDoc.data() as Map<String, dynamic>;
var referenceSnapshot = userData["someReference"].get();
});
})
I was trying to show my products in the homepage by taking from firestore collections and show it using StreamBuilder. but what my homescreen shows is its returning 'hihihihi'. I have used the correct collection reference with the correct field name.
Your help in this case will help a beginner flutter developer to complete his university project.
Thanks
Here is my code
Container(
height: 190,
child: StreamBuilder(
stream: collectionReference.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.only(left: 16, right: 6),
itemCount: 4,
itemBuilder: (context, index) {
children:
snapshot.data!.docs.map(
(e) => Container(
margin: EdgeInsets.only(right: 10),
height: 199,
width: 344,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 6.0,
),
],
),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Positioned(
child: Image(
image: AssetImage(
'assets/item1.png',
),
height: 200,
),
),
),
Positioned(
right: 20,
top: 10,
child: Text(
e['name'],
style: TextStyle(
color: Colors.black,
fontSize: 25,
fontFamily: 'Poppins',
fontWeight: FontWeight.bold),
),
),
Positioned(
right: 20,
bottom: 10,
child: Text(
e['price'],
style: TextStyle(
color: Colors.black,
fontSize: 30,
fontFamily: 'Poppins'),
),
),
],
),
),
);
return Center(child: Text('hi'));
});
}
return Center(child: Text('Empty'));
}),
),
The problem is that the itemBuilder should return how every item in the ListView will be built. Currently what you do is map the entire snapshot and then return a plan Text widget with hi in it.
Try the code below for the itemBuilder:
itemBuilder: (context, index) {
final e = snapshot.data!.docs[index];
return Container(
margin: EdgeInsets.only(right: 10),
height: 199,
width: 344,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 6.0,
),
],
),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Positioned(
child: Image(
image: AssetImage(
'assets/item1.png',
),
height: 200,
),
),
),
Positioned(
right: 20,
top: 10,
child: Text(
e['name'],
style: TextStyle(
color: Colors.black,
fontSize: 25,
fontFamily: 'Poppins',
fontWeight: FontWeight.bold),
),
),
Positioned(
right: 20,
bottom: 10,
child: Text(
e['price'],
style: TextStyle(
color: Colors.black,
fontSize: 30,
fontFamily: 'Poppins'),
),
),
],
),
);
}
Also keep in mind that your itemCount is 4 and you probably want is to be:
itemCount: snapshot.data!.docs.length
So I'm trying to create an expandable card. But the problem is, I don't even know how to start with the design.
So I'm trying to achieve this output
And this is my current progress
I tried putting two containers in a column, but it just doesn't look right.
Can someone please help me out. I need to achieve the top part of the card.
This is the code for my current progress
Widget buildTabCards() {
return Container(
padding: EdgeInsets.only(
top: 10.0,
left: 10,
right: 10,
),
child: Column(children: [
Card(
elevation: 5.0,
color: Colors.white,
child: Padding(
padding: EdgeInsets.only(
top: 7,
bottom: 10,
),
child: Column(
children: <Widget>[
buildCardDateandTime(),
buildCardAvatar(),
],
),
),
),
Widget buildCardDateandTime() {
return Container(
child: Row(
children: [
Padding(
padding: EdgeInsets.only(
left: 15,
right: 5,
top: 2,
),
child: Icon(
MdiIcons.clockOutline,
size: 22,
color: AppColors.blue,
),
),
Text(
"12 June, 2021, 8:00 AM",
style: TextStyle(
fontFamily: "Poppins",
color: Colors.black87,
letterSpacing: 0.3,
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
SizedBox(width: 5),
Padding(padding: EdgeInsets.only(left: 50)),
IconButton(
icon: Icon(
MdiIcons.fromString('dots-vertical'),
size: 30,
color: AppColors.blue,
),
onPressed: () {
Navigator.of(context).pop();
},
)
],
),
);
}
Widget buildCardAvatar() {
return Padding(
padding: EdgeInsets.only(
left: 25,
top: 5,
bottom: 10,
),
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
Container(
padding: EdgeInsets.all(15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(200),
),
color: Colors.red,
),
child: Text(
"JS",
style: TextStyle(
fontSize: 18.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
SizedBox(
width: 5.0,
),
Padding(padding: EdgeInsets.only(left: 10)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"John Renzo",
style: TextStyle(
fontSize: 20.0,
color: Colors.black54,
fontWeight: FontWeight.w500,
),
),
Text(
"Sangalang",
style: TextStyle(
fontSize: 20.0,
color: Colors.black54,
fontWeight: FontWeight.w500,
),
)
]))
]));
}
First declare a variable
bool extended = false;
then
Padding(
padding: const EdgeInsets.only(left: 12.0, right: 12.0, top: 9.0, bottom: 9.0),
child: Container(
width: MediaQuery.of(context).size.width,
child: InkWell(
onTap: () {
setState(() {
if (extended == null || !extended)
extended = true;
else
extended = false;
});
},
enableFeedback: false,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
child: Center(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10.0,
),
Row(
children: <Widget>[
Expanded(
child: Text(
'Text',
style: TextStyle(fontSize: 16.0),
),
),
Icon(
extended ? Icons.keyboard_arrow_down : Icons.keyboard_arrow_right,
size: 26,
color: Colors.grey,
)
],
),
SizedBox(
height: 10.0,
),
extended
? Container(
height: 100,
)
: Container()
],
),
),
),
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(7.0),
),
boxShadow: <BoxShadow>[
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.09),
offset: Offset(0.0, -2.0),
blurRadius: 12.0,
),
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.09),
offset: Offset(0.0, 6.0),
blurRadius: 12.0,
),
],
),
),
);
You can use ExpansionPanel to achieve your results
List<bool> isExpanded = []; //the size/length should be equal to the size of your data list
ExpansionPanelList(children: [
//generate the panels from your data list
ExpansionPanel(
headerBuilder: (context, isExpanded) {
return _headerHere();
},
body: _bodyHere(),
isExpanded: isExpanded[0], //index of your card
canTapOnHeader: true,// to make the complete header clickable
)
],
expansionCallback: (panelIndex, expanded) {
setState(() {
isExpanded[panelIndex] = !expanded;
});
},
),
I am having problem when I used the scrollcontroller to controll the gridview. I am having the error ( type 'String' is not a subtype of type 'int' of 'index'). But it was perfectly working before using the scrollcontroller. I don't where i need to change in order to remove this error. I also check the other issues regarding this in stackoverflow but couldn't get it. Can anyone check and tell me what can be change here in order to remove the error and show the data and also if my condition is right for loading 10 data in every scroll end.
import 'dart:convert';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:gridview_screoll/grid_content.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'constant.dart';
class ScrollableGrid extends StatefulWidget {
#override
_ScrollableGridState createState() => _ScrollableGridState();
}
class _ScrollableGridState extends State<ScrollableGrid> {
List data = [];
bool isLoading = false;
ScrollController _scrollController;
int pageCount = 1;
#override
void initState() {
// TODO: implement initState
super.initState();
this.fetchTopProducts();
addItemIntoLisT(pageCount);
_scrollController = new ScrollController(initialScrollOffset: 5.0)
..addListener(_scrollListener);
}
_scrollListener() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
setState(() {
isLoading = true;
if (isLoading) {
pageCount = pageCount + 1;
addItemIntoLisT(pageCount);
}
});
}
}
void addItemIntoLisT(var pageCount) {
for (int i = (pageCount * 10) - 10; i < pageCount * 10; i++) {
fetchTopProducts();
isLoading = false;
}
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
fetchTopProducts() async {
setState(() {
isLoading = true;
});
var url = base_api + "api_frontend/top_products";
var response = await http.get(url);
print(response.body);
if (response.statusCode == 200) {
setState(() {
data.add(json.decode(response.body)['top_products']);
isLoading = false;
});
} else {
setState(() {
data = [];
isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.1,
backgroundColor: Colors.indigo,
title: Text('GridControll'),
//backgroundColor: Color.fromRGBO(244, 246, 249, 1),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * 88/100,
color: Color.fromRGBO(244, 246, 249, 1),
margin: const EdgeInsets.only(
left: 0.0, bottom: 2.0, right: 0.0, top: 0),
child: getBody2(),
),
],
),
),
);
}
Widget getBody2() {
if (isLoading || data.length == 0) {
return Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(primary)));
}
return StaggeredGridView.countBuilder(
padding: const EdgeInsets.all(10.0),
controller: _scrollController,
shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
crossAxisCount: 2,
itemCount: data.length - 1,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
//builder: (context) => ProductDetails(item: data2[index]),
builder: (context) => productDetail(data[index]),
),
);
},
child: cardItem2(data[index]));
},
staggeredTileBuilder: (int index) => StaggeredTile.fit(1),
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
);
}
}
Here is grid_content.dart:
import 'package:html_unescape/html_unescape.dart';
import 'package:flutter/material.dart';
Widget cardItem2(item) {
// var img = item['thumbnail'];
// var thumbnail = base_api+"uploads/product_thumbnails/"+img;
var productId = item['product_id'];
var thumbnail = item['thumbnail'];
var unescape = new HtmlUnescape();
var name = unescape.convert(item['name']);
var unit = item['unit'];
var discount = item['discount'];
var price = item['price'];
var discountPrice = item['discount_price'];
return discount != '0%' ? Card(
elevation: 6,
shadowColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(9.0)),
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: [
Column(
children: <Widget>[
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(9), topLeft: Radius.circular(9)),
child: FadeInImage.assetNetwork(
placeholder: 'assets/loading_animated.gif',
image: thumbnail,
height: 110,
width: double.infinity,
fit: BoxFit.cover,
),
),
],
),
Padding(
padding: const EdgeInsets.only(left:6.0, right: 6.0),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 16.0,
color: Colors.black87,
fontWeight: FontWeight.w100,
),
),
Text(
unit,
style: TextStyle(
fontSize: 12.0,
color: Colors.black45,
fontWeight: FontWeight.w100,
),
),
Row(
children: [
Expanded(
flex: 2,
child: Text(
discountPrice,
style: TextStyle(
fontSize: 16.0,
color: Colors.green,
fontWeight: FontWeight.w500,
),
),
),
Expanded(
flex: 2,
child: Text(
price,
style: TextStyle(
fontSize: 12.0,
color: Colors.black38,
fontWeight: FontWeight.w500,
decoration: TextDecoration.lineThrough,
),
),
),
ButtonTheme(
padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0), //adds padding inside the button
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, //limits the touch area to the button area
minWidth: 0, //wraps child's width
height: 25,
child: FlatButton(
minWidth: 5,
height: 40,
color: Color.fromRGBO(100, 186, 2, 1),
onPressed: () {
},
child: Icon(Icons.shopping_cart, color: Colors.white,),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(color: Color.fromRGBO(100, 186, 2, 1),)),
),
),
],
),
],
),
),
),
],
),
),
],
),
],
),
) : Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(9.0)),
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: [
Column(
children: <Widget>[
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(9), topLeft: Radius.circular(9)),
child: FadeInImage.assetNetwork(
placeholder: 'assets/loading_animated.gif',
image: thumbnail,
height: 110,
width: double.infinity,
fit: BoxFit.cover,
),
),
],
),
Padding(
padding: const EdgeInsets.only(left:6.0, right: 6.0),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 16.0,
color: Colors.black87,
fontWeight: FontWeight.w100,
),
),
Text(
unit,
style: TextStyle(
fontSize: 12.0,
color: Colors.black45,
fontWeight: FontWeight.w100,
),
),
Row(
children: [
Expanded(
flex: 1,
child: Text(
price,
style: TextStyle(
fontSize: 15.0,
color: Colors.green,
fontWeight: FontWeight.w500,
),
),
),
ButtonTheme(
padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
minWidth: 0, //wraps child's width
height: 25,
child: FlatButton(
minWidth: 10,
//height: 40,
color: Color.fromRGBO(100, 186, 2, 1),
onPressed: () {
},
child: Icon(Icons.shopping_cart, color: Colors.white,),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(color: Color.fromRGBO(100, 186, 2, 1),)),
),
),
],
),
],
),
),
),
],
),
),
],
),
],
),
);
}
productDetail(item) {
// var img = item['thumbnail'];
// var thumbnail = base_api+"uploads/product_thumbnails/"+img;
var productId = item['product_id'];
var thumbnail = item['thumbnail'];
var unescape = new HtmlUnescape();
var name = unescape.convert(item['name']);
var discount = item['discount'];
var price = item['price'];
var disPrice= item['discount_price'];
var unit = item['unit'];
return Scaffold(
appBar: AppBar(
elevation: 0.1,
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: Colors.red,
title: Center(
child: Padding(
padding: const EdgeInsets.only(right: 50),
child: Text(
'Product Details',
style: TextStyle(color: Colors.white),
),
),
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 15, right: 25.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.favorite,
),
],
),
onTap: () {},
),
)
],
),
body: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: FadeInImage.assetNetwork(
placeholder: 'assets/black_circle.gif',
image: thumbnail,
height: 210,
width: 360,
fit: BoxFit.cover,
),
),
),
Center(
child: Card(
color: Colors.white38,
child: Padding(
padding: const EdgeInsets.only(left: 12.0, right: 12, top: 4, bottom: 4),
child: Text(
unit,
style: TextStyle(
fontSize: 11,
color: Colors.black87,
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Center(
child: discount != '0%' ? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
disPrice,
style: TextStyle(
fontSize: 22,
color: Colors.black87,
fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
price,
style: TextStyle(
fontSize: 18,
color: Colors.black54,
decoration: TextDecoration.lineThrough,
),
),
),
],
): Text(
price,
style: TextStyle(
fontSize: 22,
color: Colors.black87,
fontWeight: FontWeight.bold),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Center(
child: Text(
name,
style: TextStyle(
fontSize: 18,
color: Colors.black54,
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Divider(),
),
Container(
child: Center(
child: Text(
'Quantity',
style: TextStyle(color: Colors.black45, fontSize: 15),
),
),
),
Container(
child: Center(
child: Text(
'1',
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.bold),
),
),
//child: Text(store.activeProduct.qty.toString()),
),
Padding(
padding: const EdgeInsets.only(
left: 100.0, right: 100.0, bottom: 10.0),
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
side: BorderSide(color: Color.fromRGBO(41, 193, 126, 1)),
),
color: Color.fromRGBO(41, 193, 126, 1),
padding: EdgeInsets.only(top: 8, bottom: 8),
child: Center(
child: Text(
'BUY NOW',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
onPressed: () {
}),
),
Padding(
padding: const EdgeInsets.only(
left: 100.0, right: 100.0, bottom: 10.0),
child: FlatButton(
padding: EdgeInsets.only(top: 8, bottom: 8),
child: Center(
child: Text(
'ADD TO CART',
style: TextStyle(color: Color.fromRGBO(41, 193, 126, 1), fontSize: 16),
),
),
onPressed: () {
}),
),
],
),
),
),
);
}
Here is the json file:
{
"top_products": [
{
"product_id": "63",
"category_id": "59",
"name": "Ice Cream",
"price": "$9",
"discount_price": "$8.91",
"discount": "1%",
"unit": "3 kg",
"thumbnail": "http://192.168.0.105/uploads/product_thumbnails/72908baa78a2db38f678283a2e483903.jpg"
},
{
"product_id": "65",
"category_id": "47",
"name": "Malta",
"price": "$5",
"discount_price": "$4.5",
"discount": "10%",
"unit": "1 kg",
"thumbnail": "http://192.168.0.105/uploads/product_thumbnails/a63dcb5e4f883eb946585d287d25c397.jpg"
},
{},
{},
{},
...
],
"message": "Top hundred products",
"status": 200,
"validity": true
}
======== Exception caught by widgets library =======================================================
The following _TypeError was thrown building:
type 'String' is not a subtype of type 'int' of 'index'
When the exception was thrown, this was the stack:
#0 cardItem2 (package:gridview_screoll/grid_content.dart:7:23)
#1 _ScrollableGridState.getBody2.<anonymous closure> (package:gridview_screoll/scroll_grid.dart:130:20)
#2 SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:449:22)
#3 SliverVariableSizeBoxAdaptorElement._build.<anonymous closure> (package:flutter_staggered_grid_view/src/widgets/sliver.dart:144:38)
#4 _HashMap.putIfAbsent (dart:collection-patch/collection_patch.dart:140:29)
...
====================================================================================================
itemCount: data.length - 1,
Change this to this:
itemCount: data.length;