how to fix widget render issue in flutter app - flutter

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

Related

How do fix this error "Null is not a subtype of type DocumentSnaphot<object?>

I am using the Streambuilder widget to build a real-time response screen. Everything works well. But when I navigate to the page from the particular complaints screen(the reason why the postId and postusername variables at the beginning) I get red error screen that disappears after a few seconds. This is the error I get "Another exception was thrown: type 'Null' is not a subtype of type 'DocumentSnapshot<Object?>'"
class CommentsScreen extends StatefulWidget {
final String postId;
final String postusername;
const CommentsScreen(
{Key? key, required this.postId, required this.postusername})
: super(key: key);
#override
_CommentsScreenState createState() => _CommentsScreenState();
}
class _CommentsScreenState extends State<CommentsScreen> {
final TextEditingController commentEditingController =
TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: primaryColor,
title: const Text(
'Responses',
),
centerTitle: false,
),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('posts')
.doc(widget.postId)
.collection('comments')
.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.hasError) {
return const Center(child: Text("Something went wrong"));
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot answers = snapshot.data!.docs[index];
DateTime postDate = answers['datePublished'].toDate();
String formattedDate =
DateFormat.yMMMd().add_jm().format(postDate);
return Padding(
padding: const EdgeInsets.all(primaryPadding),
child: Card(
elevation: 15,
shadowColor: secondaryColor,
child: Padding(
padding: const EdgeInsets.all(primaryPadding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
CircleAvatar(
backgroundColor: secondaryColor,
radius: 18,
child: Text(
answers['username'][0],
style: const TextStyle(
color: primaryColor,
fontSize: fontSizeFive),
),
),
const SizedBox(
width: 5,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(answers['username'],
style: const TextStyle(
fontSize: fontSizeFour,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.normal)),
Text(formattedDate,
style: const TextStyle(
fontSize: fontSizeTwo,
fontStyle: FontStyle.italic))
],
)
],
),
const Divider(
height: 10,
),
Text(
answers['answers'],
style: const TextStyle(fontSize: fontSizeThree),
)
],
),
),
),
);
});
},
),
// text input
bottomNavigationBar: SafeArea(
child: StreamBuilder<Object>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
DocumentSnapshot user = snapshot.data;
String pic = user['photoUrl'];
return Container(
height: kToolbarHeight,
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
padding: const EdgeInsets.only(left: 16, right: 8),
child: Row(
children: [
CircleAvatar(
backgroundImage: NetworkImage(pic),
radius: 20,
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 16, right: 8, bottom: 10),
child: TextField(
controller: commentEditingController,
decoration: const InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(circularRadius))),
),
),
),
),
],
),
);
}),
),
);
}
}
I have tried a few options like playing around will the null check operators but nothing seems to sort this issue. Any help, please?
below is how my terminal looks like
You need to check whether the snapshot has error or has data before trying to get the data. In this example, I display error message if the snapshot has error and I display circular progress indicator if snapshot does not have data. I only display the Container if it passes both of these check.
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return const Center(child: Text("Something went wrong"));
}
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
DocumentSnapshot user = snapshot.data;
String pic = user['photoUrl'];
return Container(

News pages doesn't show article or blogs after building apk

I'm creating a flutter project on which it consist of news feature sadly after building an apk and installing it to try in become an empty screen with grey shade, i also try to test it on my phone and this is what happen i dont know where the bugs came from.. please help me
here's the code
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'Article_View.dart';
import 'News_Categories.dart';
import 'helper/Data.dart';
import 'helper/News.dart';
import 'model/Article_Model.dart';
import 'model/CategoryModel.dart';
class NewsHomePage extends StatefulWidget {
#override
_NewsHomePageState createState() => _NewsHomePageState();
}
class _NewsHomePageState extends State<NewsHomePage> {
List<CategoryModel> categories = <CategoryModel>[];
List<ArticleModel> articles = <ArticleModel>[];
bool _loading = true;
//bannerads
late BannerAd _bannerads;
bool _isAdsLoaded = false ;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
_initBannerAds();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
_loading = false;
});
}
_initBannerAds(){
_bannerads = BannerAd(
size: AdSize.banner,
// ignore: deprecated_member_use
adUnitId: "ca-app-pub-8634651641429291/4830511818",
listener: BannerAdListener(
onAdLoaded: (ad){
setState(() {
_isAdsLoaded =true;
});
},
onAdFailedToLoad: (ad,error){}
),
request: const AdRequest()
);
_bannerads.load();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
elevation: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Stock '),
Text(
'News',
style: TextStyle(
color: Colors.black54,
),
),
],
),
centerTitle:true,
bottom: const PreferredSize(
preferredSize: Size.zero,
child: Text("Powered by news.org")),
),
body: _loading
? Container(
child: const Center(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
///Categories
Container(
padding: const EdgeInsets.symmetric(horizontal: 22.0),
height: 90.0,
child: Expanded(
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageAssetUrl,
categoryName: categories[index].categoryName,
);
}),
),
),
///Blogs
Container(
padding: const EdgeInsets.only(top: 16.0),
child: Expanded(
child: ListView.builder(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageURL: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
url: articles[index].url,
);
},
),
),
),
],
),
),
),
bottomNavigationBar: _isAdsLoaded?SizedBox(
height: _bannerads.size.height.toDouble(),
width: _bannerads.size.width.toDouble(),
child: AdWidget(ad: _bannerads),
)
:const SizedBox(),
);
}
}
class CategoryTile extends StatelessWidget {
final String imageUrl, categoryName;
const CategoryTile({required this.imageUrl, required this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryNews(
category: categoryName.toLowerCase(),
),
),
);
},
child: Container(
margin: EdgeInsets.only(right: 10.0),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: imageUrl != null
? CachedNetworkImage(
imageUrl: imageUrl,
width: 120,
height: 60.0,
fit: BoxFit.cover,
)
: Image.network(
imageUrl,
width: 120.0,
height: 60.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6),
),
width: 120,
height: 60.0,
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 18.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageURL, title, desc, url;
BlogTile(
{required this.imageURL,
required this.title,
required this.desc,
required this.url});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ArticleView(
blogUrl: url,
)),
);
},
child: Container(
margin: const EdgeInsets.only(bottom: 16.0, left: 10.0, right: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: imageURL != null
? CachedNetworkImage(
imageUrl: imageURL,
)
: Image.network(imageURL),
),
const SizedBox(
height: 8.0,
),
Text(
title,
style: const TextStyle(
//color: Colors.black87,
fontSize: 17.0,
fontWeight: FontWeight.w500,
),
),
const SizedBox(
height: 8.0,
),
Text(
desc,
style: const TextStyle(
//color: Colors.black54,
),
),
],
),
),
);
}
}
and here's the screen shots of the app
[![debugging app][1]][1]
[![build app][2]][2]
[1]: https://i.stack.imgur.com/tvBsG.jpg
[2]: https://i.stack.imgur.com/wOuxS.jpg
Check if this line exists in android/app/src/main/AndroidManifest.xml file. If it doesn't add it right below the package name line. This will grant the app INTERNET permission so it can access it & display the data from the internet.
<uses-permission android:name="android.permission.INTERNET"/>
Flutter by default only adds the INTERNET permission in debug mode. When you build an APK in release mode, you have to explicitly add the permission by including the above line.
More info here.

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);
},

How to remove empty spaces generated by grid view

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.