How to remove empty spaces generated by grid view - flutter

I want to apply categorise selection for my flutter app. I'm a beginner in flutter. I've tried to my very best to get here but I don't know how to remove these empty spaces.
In the body of the homescreen.dart I've written the following code.
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: KDefaultPadding),
child: GridView.builder(
itemCount: products.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.75,
mainAxisSpacing: KDefaultPadding,
crossAxisSpacing: KDefaultPadding,
),
itemBuilder: (context, index) => ItemCard(
product:
products[index].tag == "chicken" ? products[index] : null,
press: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(
product: products[index],
),
),
),
),
),
),
),
and in the item card.dart I've written the following.
class ItemCard extends StatelessWidget {
final Product product;
final Function press;
const ItemCard({
Key key,
this.product,
this.press,
}) : super(key: key);
#override
Widget build(BuildContext context) {
if (product != null) {
return GestureDetector(
onTap: press,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.all(KDefaultPadding),
// height: 180,
// width: 160,
decoration: BoxDecoration(
color: product.color,
borderRadius: BorderRadius.circular(16),
),
child: Hero(
tag: "${product.id}",
child: Image.asset(
product.image,
)),
),
Padding(
padding:
const EdgeInsets.symmetric(vertical: KDefaultPadding / 4),
child: Text(
product.title,
style:
TextStyle(color: kTextColor, fontWeight: FontWeight.bold),
),
),
Text(
"$kCurrency${product.price}",
style: TextStyle(
color: kTextLightColor, fontWeight: FontWeight.bold),
)
],
),
);
} else {
return Container();
}
}
}
and the output I got is this.
initial is this...
Can someone help me out please?

Change this products.length to products.where((product) => product.tag == 'chicken').length to do not put unexpected product into GridView.

Related

how to fix widget render issue in flutter app

I am getting that infamous error, which I am not able to resolve.
RenderBox was not laid out: RenderRepaintBoundary#03a24 relayoutBoundary=up14 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 2001 pos 12: 'hasSize
I tried all sorts of wrapping of widgets. The error is on the Container(). In that container I am trying to display 10 newest products, scrolled horizontaly, and fetched from the firestore database. Below, I display list of outlets, scrolled vertically and they do not cause any problem, neither the horizontal scrolling widget, which displays categories.
I have a tabscreen and in the TabView I have this class:
class UserHomeMerch extends StatefulWidget {
UserHomeMerch({Key? key}) : super(key: key);
#override
UserHomeMerchState createState() => UserHomeMerchState();
}
Class UserHomeMerchState extends State<UserHomeMerch> {
#override
Widget build(BuildContext context) {
final outletData = Provider.of<OutletData>(context);
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: const BoxDecoration(
image: DecorationImage(image: AssetImage("assets/images/background.jpg"),
fit: BoxFit.cover,),
),
),
FutureBuilder(
future: outletData.getAllOutlets(context),
builder: (ctx, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting ||
snapshot.data == null) {
return Center(
child: CircularProgressIndicator(color: color4),
);
}
var sd = snapshot.data;
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
Languages.of(context)!.category+':',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 21,
color: color1,
),
),
),
Categories(),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
Languages.of(context)!.newProducts,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 21,
color: color1,
),
),
),
Container( =====> this is the error line
height: 250,
child: StreamBuilder<QuerySnapshot>(
stream: productsRef
.orderBy('timestamp', descending: true)
.limit(10)
.snapshots(),
builder: (context, snapshot) {
return (snapshot.connectionState == ConnectionState.waiting)
? Center(child: CircularProgressIndicator(color: color4,))
: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot data = snapshot.data!.docs[index];
return ProductItem(
productId: data[productId],
productName: data[productName],
productDescription: data[prodDesc],
productPrice: data[productPrice],
count: data[countInStock],
images: data['productImagesUrl'],
outletID: data[outletId],
merchId: data[merchantId]
);
});
},
)),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
Languages.of(context)!.producers+':',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 21,
color: color1,
),
),
),
sd.length == 0
? Center(
child: Text(Languages.of(context)!.noOrg),
)
: ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (ctx, index) {
return OutletItem(
outletName: sd[index][outletName],
id: sd[index][outletId],
category: sd[index][category],
outletImage: sd[index][outletImg],
outletRating: sd[index][outletRating],
merchId: sd[index][merchantId],
);
},
itemCount: sd.length,
),
],
),
);
},
),
]),
));
}
}
My productItem widget is a card, with the tap displays bottomModal, here it is:
class ProductItem extends StatelessWidget {
final String productId;
final String productName;
final String productDescription;
final num productPrice;
final num count;
final List<dynamic> images;
final String outletID, merchId;
ProductItem(
{required this.productId,
required this.productName,
required this.productDescription,
required this.productPrice,
required this.count,
required this.images,
required this.outletID,
required this.merchId});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30)),
elevation: 20,
color: color2.withOpacity(0.5),
shadowColor: color2.withOpacity(0.2),
child: Column(
children: [
Container(
alignment: Alignment.center,
child: Image.network(
images.first,
//height: 500,
//width: 500,
fit: BoxFit.cover,
),
height: 250,
//width: 100,
),
ListTile(
selectedColor: Colors.white70,
title: Text(
productName,
overflow: TextOverflow.fade,
softWrap: true,
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
"₮ ${NumberFormat.decimalPattern().format(productPrice)}",
),
trailing: TextButton.icon(
onPressed: () {
showModal(context, productId, productName, productDescription, productPrice, images, count, outletID, merchId);
},
icon: Icon(
Icons.add,
color: Colors.black54,
),
label: Text(
Languages.of(context)!.seeProf,
),
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: BorderSide(
color: Colors.black54,
),
),
),
),
),
),
Divider(thickness: 2),
],
),
),
);
}
}
Please, help me fix this issue. Thank you very much in advance!
I think the error is on the second listview builder. try wrapping it with an Expanded widget. if not and you are 100% sure on it's on the horizontal listview builder try giving the container a width and wrapping the listview builder with an Expanded Widget.
I hope this helps

Grivdview search not working properly flutter

I have a gridview,i have implemented search,search is working fine,but the viewing of search item is not shows properly,
Before search
This how my gridview show after searching a item
Code
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 6 / 5,
// crossAxisCount: 2,
crossAxisSpacing: 0,
mainAxisSpacing: 0),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
SubCategoryModel data = sub_category_model[index];
if (searchController.text.isEmpty) {
return GestureDetector(
child: Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 0,
child: Container(
width: 100,
height: 100.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(
fit: BoxFit.fill,
imageUrl: Urls.BASE_IMAGE_URL +
data.image.toString(),
placeholder: (context, url) => Center(
child: CircularProgressIndicator()),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
)),
Expanded(
flex: 0,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 10),
child: Text(
data.name,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 13),
),
),
)
],
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OnlinecartSubitems(data.id.toString(),Category_Name),
),
);
},
);
} else if (data.name.contains(searchController.text) ||
data.name.toLowerCase().contains(searchController.text) ||
data.name.toUpperCase().contains(searchController.text)) {
return GestureDetector(
child: Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 0,
child: Container(
width: 100,
height: 100.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(
fit: BoxFit.fill,
imageUrl: Urls.BASE_IMAGE_URL +
data.image.toString(),
placeholder: (context, url) => Center(
child: CircularProgressIndicator()),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
)),
Expanded(
flex: 0,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 10),
child: Text(
data.name,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 13),
),
),
)
],
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OnlinecartSubitems(data.id.toString(),Category_Name),
),
);
},
);
} else {
return Container();
}
},
childCount: sub_category_model.length,
),
)
Why not make a new list each time the search matches an item. Then, build a New GridView object based on the newly created list. Whenever your TextView is empty, you return the original list.
For Instance
//Create Search List
List<Object> searchList = [];
//Check if SearchTextView is empty or not with a ternary Operator
controller.text.isEmpty?
//Build your GridView based on the Original List
GridView.count(
...
itemCount: mainList.length,
...
) //Replace with you SliverGrid
//Build your GridView based on the Search List
: GridView.count(
...
itemCount: searchList.length
...
),//Replace with you SliverGrid
You can Replace my GridView with your SilverGrid widget.
The full Code (Spoiler alert: Very long):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key key, #required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//Search TextField Controller
final _searchController = TextEditingController();
List<Fruit> mainList = [
Fruit(name: 'Apple', imageUrl: 'https://images.pexels.com/photos/102104/pexels-photo-102104.jpeg'),
Fruit(name: 'Banana', imageUrl: 'https://images.pexels.com/photos/5945848/pexels-photo-5945848.jpeg'),
Fruit(name: 'Pineapple', imageUrl: 'https://images.pexels.com/photos/1071878/pexels-photo-1071878.jpeg'),
Fruit(name: 'Mango', imageUrl: 'https://images.pexels.com/photos/918643/pexels-photo-918643.jpeg'),
];
List<Fruit> searchList = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 60.0,
child: TextFormField(
controller: _searchController,
onChanged: (text){
final String queryString = _searchController.text;
setState((){
if(queryString.isNotEmpty){
for(final fruit in mainList){
if(fruit.name.contains(queryString)){
searchList.add(fruit);
} else{
searchList.remove(fruit);
}
}
}else{
searchList.clear();
}
});
}
),
),
Expanded(
child: _searchController.text.isEmpty
? GridView.count(
crossAxisCount: 2,
children: mainList.map((fruit)=> CardWidget(fruit: fruit)).toList(),
)
:GridView.count(
crossAxisCount: 2,
children: searchList.map((searchedFruit)=>CardWidget(fruit: searchedFruit)).toList()
),
),
],
),
);
}
}
Create a Class to hold Fruit
class Fruit{
final String imageUrl;
final String name;
Fruit({this.imageUrl, this.name});
}
Create widget to be built for each fruit object found in the mainList
//Card Widget
class CardWidget extends StatefulWidget{
final Fruit fruit;
CardWidget({this.fruit});
#override
_CardWidgetState createState()=> _CardWidgetState();
}
class _CardWidgetState extends State<CardWidget>{
#override
Widget build(BuildContext context){
return Container(
width: 100.0,
height: 140.0,
child: Column(
children:[
Image(image: NetworkImage(widget.fruit.imageUrl)),
SizedBox(height: 10.0),
Text(widget.fruit.name),
]
)
);
}
}
Try it and let see
I have fixed the issue with help of Benedict and Farhan Syah thanks for the idea and some codes
Initialize variables
//Search controller for textfield
TextEditingController searchController = TextEditingController();
//For show list data first
List<SubCategoryModel> sub_category_model = [];
//for searchresult list
List<SubCategoryModel> _searchResult = [];
View
_searchResult.length != 0 ||searchController.text.isNotEmpty?SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 6 / 5,
// crossAxisCount: 2,
crossAxisSpacing: 0,
mainAxisSpacing: 0),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
SubCategoryModel data = _searchResult[index];
return GestureDetector(
child: Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 0,
child: Container(
width: 100,
height: 100.0,
child: ClipRRect(
borderRadius:
BorderRadius.circular(10.0),
child: CachedNetworkImage(
fit: BoxFit.fill,
imageUrl: Urls.BASE_IMAGE_URL +
data.image.toString(),
placeholder: (context, url) => Center(
child:
CircularProgressIndicator()),
errorWidget: (context, url, error) =>
Icon(Icons.error),
),
),
)),
Expanded(
flex: 0,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 10),
child: Text(
data.name,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 13),
),
),
)
],
),
),
onTap: () {
},
);
},
childCount: _searchResult.length,
),
):SliverGrid(//use same code above with **sub_category_model.length**)
Search widget
Widget _SearchText() {
return Container(
width: 360,
height: 65,
color: Colors.transparent,
child: new Padding(
padding: const EdgeInsets.only(top: 10, left: 10, right: 10),
child: new Card(
elevation: 8,
child: TextField(
decoration: new InputDecoration(
filled: true,
hintStyle: TextStyle(fontSize: 11.5),
hintText: 'Search by Name',
suffixIcon: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
searchController.clear();
_searchResult.clear();
},
child: Icon(Icons.cancel_rounded,
color: Color.fromRGBO(34, 83, 148, 1))),
prefixIcon:
Icon(Icons.search, color: Color.fromRGBO(34, 83, 148, 1)),
border: InputBorder.none),
onChanged: onSearchTextChanged,
controller: searchController,
),
),
),
);
}
Onchanged function for searching through list
onSearchTextChanged(String text) async {
//clear search data before typing
_searchResult.clear();
if (text.isEmpty) {
setState(() {});
return;
}
//use searchcontroller text and loop through list of api data and add the result to _searchResult
sub_category_model.forEach((searchValue) {
if (searchValue.name.toLowerCase().contains(text))
_searchResult.add(searchValue);
});
setState(() {});
}
You are returning Container() when the search condition doesn't match. Container itself will take a place of a widget, hence, it will be an item of the grids.
To test this, you can try putting something inside the container, such as:
Container(
child: Text('This grid is not empty)
)
The problem with this, is if you have 12 items in the data, no matter your search result, it will still build 12 items (including the empty container)
To solve this, you need a better way to filter the data, such as using a list to filter, and then passing the list data to the grid builder.
The concept is like this:
Original list : 10 items
Newlist based on the search: 5 items
The grid builder will build the items based on the list provided.

Flutter OnTap Listview item

I'm new to flutter, may I know how to get different outputs when I click on each item? I have total of 3 lists, for each item, I want to get their respective output and now I only can get the same outputs for each item. How to get different outputs when I click on it? Thanks all.
this is my ListView coding :
class _CatState extends State<Cat> {
List<String> categories = ["Furniture", "Lighting", "Decoration"];
int selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: SizedBox(
height: 25,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index) => buildCategory(index),
),
));
}
Widget buildCategory(int index) {
return GestureDetector(
onTap: () {
setState(() {
selectedIndex = index;
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
categories[index],
style: TextStyle(
fontSize: 15,
color: selectedIndex == index ? Colors.black : Colors.black45,
),
),
Container(
margin: EdgeInsets.only(top: DefaultPadding / 4), //top padding
height: 2,
width: 50,
color: selectedIndex == index
? Colors.blueAccent[200]
: Colors.transparent,
)
],
When onTap the item:
class ItemCard extends StatelessWidget {
final Product product;
final Decor decoration;
final Light light;
final Function press;
const ItemCard({
Key key,
this.press,
this.product,
this.decoration,
this.light,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: press,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Container(
padding: EdgeInsets.all(2.0),
// height: 180,
// width: 160,
child: ClipRRect(
borderRadius: BorderRadius.circular(25.0),
child: Image.asset(
product.img, // products image
)),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: DefaultPadding / 4),
child: Text(
product.name, // products name
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
Text(
product.price,
textAlign: TextAlign.center,
style: TextStyle(fontStyle: FontStyle.italic),
)
],
),
Use switch case if it is static. For example on itemBuilder in Gridview:
ItemCard(
product:furniture[index],
press: _onPressed(index),
)
and in onPressed method, do whatever you want:
_onPressed(int index){
switch(index):
case 0:
your code:
break;
case 1:
//code
}
so by this you can make different onTap function

How to fetch specific data from API into flutter app

I am a beginner in flutter.
I have created two ListView Builder where one ListView.builder is inside another builder as given below.
I have a list of categories which is inside one listview.builder and other are the list of products which also listview.builder Wrapped inside the above listview build>
So now i need to display the only items belonging to the 1st listview builder which means If I have a categories named soup (1st ListView.builder) Now i need to display only the products that belongs to soup categories from 2nd Listview.Builder but all the products are listed inside all the categories list. So, Please help me to find solution any help would be appriciated.Thank you in advance.
Below are the codes.
//lib/routes/menu_description.dart(File name)
import 'package:flutter/material.dart';
import '../api_service.dart';
import 'package:html/parser.dart';
import 'package:percent_indicator/percent_indicator.dart';
class MenuDescription extends StatefulWidget {
MenuDescription({Key key}) : super(key: key);
#override
_MenuDescriptionState createState() => _MenuDescriptionState();
}
int itemspressed;
class _MenuDescriptionState extends State<MenuDescription> {
#override
Widget build(BuildContext context) {
return Container(
// color: Colors.grey[200],
child: FutureBuilder(
future: fetchWpPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.separated(
separatorBuilder: (context, index) => Divider(
height: 20.0,
color: Colors.black,
),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Map wpcategoriespost = snapshot.data[index];
return Container(
color: Colors.grey[200],
child: InkWell(
splashColor: Colors.grey[800],
onTap: () {
setState(() {
itemspressed = index;
});
},
child: Padding(
padding: const EdgeInsets.only(
left: 5, right: 5, bottom: 5, top: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
"${wpcategoriespost['name']}",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Colors.lightGreen[900],
),
),
),
Center(
child: Text(
parse(("${wpcategoriespost['description']}")
.toString())
.documentElement
.text,
style:
TextStyle(fontSize: 14, color: Colors.black),
),
),
Container(
padding: EdgeInsets.only(top: 20.0),
child: Categories(),)
],
),
),
),
);
},
);
}
return new CircularPercentIndicator(
radius: 120.0,
lineWidth: 13.0,
animation: true,
percent: 1.0,
progressColor: Colors.orange,
center: new Text(
"100.0%",
style:
new TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
));
},
),
);
}
}
class Categories extends StatefulWidget {
#override
_CategoriesState createState() => _CategoriesState();
}
class _CategoriesState extends State<Categories> {
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: fetchWpPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Map wppost = snapshot.data[index];
return Card(
margin: const EdgeInsets.only(
left: 15,
right: 15,
bottom: 15,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 3,
child: InkWell(
splashColor: Colors.grey[300],
onTap: () {
setState(() {
itemspressed = index;
});
},
child: Padding(
padding: const EdgeInsets.only(
left: 12, right: 5, bottom: 12, top: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${wppost['name']}",
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Colors.lightGreen[900]),
),
Container(
height: 40,
width: 40,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
border: Border.all(color: Colors.grey[350]),
color: itemspressed == index
? Colors.grey[350]
: null,
),
child: IconButton(
iconSize: 22,
icon: Icon(
Icons.add,
color: Colors.blueAccent[400],
),
onPressed: () {
setState(() {});
print('Add to cart');
},
),
),
],
),
Text(
parse(("${wppost['description']}").toString())
.documentElement
.text,
style: TextStyle(fontSize: 14, color: Colors.black),
),
Text(
parse(("${wppost['price']} €").toString())
.documentElement
.text,
style: TextStyle(
fontSize: 15,
color: Colors.amber[700],
fontWeight: FontWeight.bold),
),
],
),
),
),
) ;
},
);
}
return new CircularPercentIndicator(
radius: 120.0,
lineWidth: 13.0,
animation: true,
percent: 1.0,
progressColor: Colors.orange,
center: new Text(
"100.0%",
style:
new TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
));
},
),
);
}
}
//lib/api_service.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<List> fetchWpPosts() async{
final response = await http.get('https://word.tkco.in/wp-json/wc/v3/products?consumer_key=ck_94114a31e4576e61a9292f961489e7701029753e&consumer_secret=cs_dd4dc6e7945d8dcd14d888bc1d0ea0806b116dfb');
var convertDatatoJson = jsonDecode(response.body);
if (response.statusCode == 200) {
}
return convertDatatoJson;
}

passing data through the widget constructor

i am missing a small piece of information about constructors, i am trying to pass some data through the widget PromotionCard( [ ... ] ) i can't see any error in my debug console i tried Cards widgets and other different stuff to show the data but i can't find out what is wrong with this code down below.
Note: when i print snapshot.data i can see it perfectly returned
any help please.
**promotions_page.dart**
class PromotionsPage extends StatefulWidget {
#override
_PromotionsPageState createState() => _PromotionsPageState();
}
class _PromotionsPageState extends State<PromotionsPage> {
Future<Result> _promotionsResultsData;
#override
void initState() {
_promotionsResultsData = PromotionApi().fetchPromotions();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
child: ListView(
physics: PageScrollPhysics(),
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Акции',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'BuffetBold',
),
),
InkWell(
onTap: () => print('Archive promotion pressed!'),
child: Text(
'Архив Акции',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
fontFamily: 'BuffetBold',
color: Colors.grey[400],
),
),
),
],
),
SizedBox(
height: 10.0,
),
Container(
child: FutureBuilder<Result>(
future: _promotionsResultsData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return GridView.builder(
padding: EdgeInsets.zero,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: (45 / 35),
crossAxisCount: 1,
),
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: snapshot.data.result.length,
itemBuilder: (BuildContext context, int index) {
//print(snapshot.data.result.length);
var promos = snapshot.data.result[index];
PromotionCard(
id: promos.id,
title: promos.title,
description: promos.description,
image: promos.image);
},
);
} else {}
return Center(
child: Text(
"Loading ...",
style: TextStyle(
fontWeight: FontWeight.w900, fontSize: 30.0),
),
);
},
),
),
],
),
],
),
),
);
}
}
i am trying to pass data to this screen
**w_promotion_card.dart**
class PromotionCard extends StatelessWidget {
final String id;
final String title;
final String description;
final String image;
PromotionCard({this.id, this.title, this.description, this.image});
#override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: 200.0,
margin: EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 10.0),
padding: EdgeInsets.zero,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(image),
alignment: Alignment.topCenter,
),
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
width: 1.5,
color: Colors.grey[300],
),
),
child: Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.zero,
child: Padding(
padding: EdgeInsets.fromLTRB(10, 170.0, 10.0, 10.0),
child: Text(
title,
style: TextStyle(
fontSize: 16.0,
fontFamily: 'BuffetRegular',
),
),
),
),
);
}
}
You missed the return statement
itemBuilder: (BuildContext context, int index) {
//print(snapshot.data.result.length);
var promos = snapshot.data.result[index];
// you have to return the widget
return PromotionCard(
id: promos.id,
title: promos.title,
description: promos.description,
image: promos.image);
},