How can I build a gridview with a dynamic height in Dart? - flutter

I am trying to build a GridView that adjusts its height automatically according to the data provided. However, I am encountering a problem where an additional line (Top Discount of the Sale) appears after the rating bar for some products, but the space for that line is not reserved for other products that do not have it. As a result, I get a RenderFlex error when I try to implement this. How can I properly handle this situation?
GridView.builder(
padding: const EdgeInsets.all(12.0),
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 6.0,
childAspectRatio: .60,
mainAxisSpacing: 6.0,
),
itemCount: state
.productListModel!.productModel!.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return InkWell(
splashFactory: NoSplash.splashFactory,
onTap: () {
Helper.push(
context,
ProductView(
productId: state.productListModel!
.productModel![index].sId,
));
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
alignment:
Alignment.bottomRight,
children: [
SizedBox(
width: WidgetStyles()
.theWidth(context),
height: WidgetStyles()
.theHeight(
context) /
4,
child: ImageView(
imageUrl: state
.productListModel!
.productModel![index]
.photos![0],
fit: BoxFit.contain,
),
),
Positioned(
right: 5,
bottom: 5,
child: Container(
padding:
const EdgeInsets
.all(8.0),
decoration:
const BoxDecoration(
color: Colors
.white,
shape: BoxShape
.circle),
child: InkWell(
onTap: () async {
String deepLink = await FirebaseDynamiclinkService
.createDynamicLink(
true,
state
.productListModel!
.productModel![
index]
.sId!);
log(deepLink);
Helper.shareProduct(
context,
'MyEComApp\n♥️ Proudly made for kerala\n\n${state.productListModel!.productModel![index].productname!}\n${state.productListModel!.productModel![index].seller!.organization!}\n*INR ${state.productListModel!.productModel![index].price!}*\n$deepLink',
state
.productListModel!
.productModel![
index]
.photos![0]);
},
child: const Icon(
Icons.share,
size: 18,
),
),
))
],
),
Helper.allowHeight(context, 5.0),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Flexible(
child: Text(
state
.productListModel!
.productModel![
index]
.productname!
.toString(),
overflow:
TextOverflow.clip,
maxLines: 1,
style:
const TextStyle(
fontSize: 13,
fontWeight:
FontWeight.w500,
),
),
),
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Flexible(
child: Text(
state
.productListModel!
.productModel![
index]
.seller!
.organization!
.toString(),
overflow:
TextOverflow.clip,
style: TextStyle(
fontSize: 10,
color: AppColors
.greyAA,
fontWeight:
FontWeight.w500,
),
),
),
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Text(
"\u{20B9} ${state.productListModel!.productModel![index].price!}",
style: TextStyle(
fontSize: 14,
color:
AppColors.black,
fontWeight:
FontWeight.bold,
),
),
Helper.allowWidth(
context, 15),
state
.productListModel!
.productModel![
index]
.price !=
state
.productListModel!
.productModel![
index]
.orginalprice
? Text(
"\u{20B9} ${state.productListModel!.productModel![index].orginalprice}",
maxLines: 1,
style:
const TextStyle(
overflow:
TextOverflow
.ellipsis,
decoration:
TextDecoration
.lineThrough,
fontSize: 14,
color:
Colors.red,
fontWeight:
FontWeight
.bold,
),
)
: const SizedBox
.shrink(),
],
),
const SizedBox(height: 8),
],
),
]),
);
},
// separatorBuilder: (context, index) {
// return const SizedBox(
// width: 10.0,
// );
// },
);

i would like to use StaggeredGridView plugins, this is my code that i've tried to use and it work properly that you might needed to create a responsive gridview that contain sort list of data
Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
child: SizedBox(
width: double.infinity,
child: StaggeredGridView.countBuilder(
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
staggeredTileBuilder: (index) => const StaggeredTile.fit(1),
mainAxisSpacing: 10,
crossAxisCount: 2,
crossAxisSpacing: 10,
itemCount: ...,
itemBuilder: (ctx, i) {
....
},
),
),
)

Related

gridview.builder is not scrollebel?

this is my program but it shows error gridview.builder is not scroll so it shows error
in this gridview it is not working properly it shows error
GridView.builder(
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: 4,
itemBuilder: (BuildContext context, int index){
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Stack(overflow: Overflow.visible,
alignment: Alignment.center,
children: [
Container(
height: 200.0,
width:170.0,
padding: EdgeInsets.only(bottom: 24.0),
decoration: BoxDecoration(
color: kLightGreyColor,
borderRadius: BorderRadius.circular(32.0),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children:[
Text("Name", style: TextStyle(fontSize: 16.0,
fontWeight: FontWeight.w600,
color: klightFontColor), ),
SizedBox(height: 12.0,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children:
List.generate(5, (index) => Image.asset("assets/images/star.png", height: 20.0,))
),
SizedBox(height: 12.0,),
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
"60 \nMin",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: klightFontColor,
),
),
Column(
children:List.generate(6, (index) => Container(
height: 2.0,
width: 2.0,
margin: EdgeInsets.only(bottom: 2),
decoration: BoxDecoration(
color: kDarkGreyColor,
borderRadius: BorderRadius.circular(2.0),
),
))
),
Text(
"Hard \nLV1",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: klightFontColor,
),
)
]),
]),
),
Positioned(
top: -190.0,
bottom: 0.0,
left: 20.0,
right: 20.0,
child:Container(
height: 80,
width:80,
child:Image.asset("assets/images/food1.png",),
)
),
]),
);
}),
I used the `singleChildscrollview()`, and `physics: ScrollPhysics(),` but still same error
just remove the shrinkWrap or set it to false and delete the SingleChildScrollView if you want the GridView to take All the space available wrap it in an Expanded Widget

Flutter-Renderflex overflow error on each item in GridView.builder()

In my project i need to display a grid of products,2 in each row. For that I am using GridView.builder() as follows :
#override
Widget build(BuildContext context) {
return Column(
children: [
const Text('New Arrivals'),
const SizedBox(height: 10),
Expanded(
child: Consumer<HomeViewModel>(
builder: (context, model, child) {
if (model.state == ViewState.idle) {
if (model.products.isEmpty) {
return const Center(
child: CircularProgressIndicator(color: Colors.black),
);
}
return GridView.builder(
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context, index) =>
ProductItem(product: model.products[index]),
itemCount: model.products.length,
);
}
return const Center(
child: CircularProgressIndicator(color: Colors.black),
);
},
),
),
],
);
}
However, this is giving an A RenderFlex overflowed by 49 pixels on the bottom. error on each item. The no. of pixels overflowed is different for different item.I have attached the screenshot for reference. What am I doing wrong and how do I fix it?
product_item.dart:
class ProductItem extends StatelessWidget {
const ProductItem({Key? key, required this.product}) : super(key: key);
final Product product;
#override
Widget build(BuildContext context) {
return Container(
width: 200,
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 200,
height: 150,
child: Image.network(product.imageUrl!),
),
const SizedBox(height: 13),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
product.category!,
softWrap: true,
style: const TextStyle(
fontSize: 10,
color: Colors.deepPurple,
height: 1.5,
fontWeight: FontWeight.w500,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
product.title!,
softWrap: true,
style: const TextStyle(
color: Colors.black54,
fontSize: 12,
height: 1.8,
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'\$ ${product.price!}',
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w600,
height: 2.4,
),
),
Image.asset('assets/icons/cart_icon.png',
width: 40, height: 40),
],
),
)
],
),
);
}
}
the problem "should" lie within:
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
product.title!,
softWrap: true,
style: const TextStyle(
color: Colors.black54,
fontSize: 12,
height: 1.8,
fontWeight: FontWeight.w500,
),
),
),
try using: AutoSizeText instead of Text
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: AutoSizeText(
product.title!,
softWrap: true,
maxLines: 1,
style: const TextStyle(
color: Colors.black54,
fontSize: 12,
height: 1.8,
fontWeight: FontWeight.w500,
),
),
),
Default childAspectRatio is 1 on GridView. The issue arise because it is not fitting inside the square. Item's size is depending on screen width. And width is controlling the height,=> aspect ratio.
You can play with size of grid item using childAspectRatio:width/height. Alternative, you can follow #Maurizio Mancini's answer.
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 4,//this
),
I have used your code to reproduce the issue. If I understood your needs right, here is the fix:
The main problem is related to childAspectRatio.
return GridView.builder(
shrinkWrap: true,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 0.75,
),
itemBuilder: (context, index) =>
ProductItem(product: model.products[index]),
itemCount: model.products.length,
);
So you need to set the aspect ratio similar to this to fix the problem.
You can access the working source code through GitHub.

Scrollbar is not visible when wrapping listView Builder with SingleChildScrollView or ListView

**> Here is my code. it contains a ListView builder which is wrapped with
RawScrollBar widget and they both wrapped with SingleChildScrollView
Widget. I want a show ScrollBar in ListView.Builder**
Scaffold(
backgroundColor: kPrimaryColor,
body: SafeArea(
child: SizedBox(
height: kGetSize(context).height,
child: Column(
children: [
const SizedBox(
height: 16,
),
const Center(
child: UserLevelDetailsContainer(),
),
Expanded(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 24, vertical: 24),
**child: SingleChildScrollView(
physics: const ScrollPhysics(),
controller: _scrollController,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'General Subjects',
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700,
fontSize: 20,
color: const Color(0xfff3c304)),
),
const SizedBox(
height: 8,
),
RawScrollbar(
thumbVisibility: true,
interactive: true,
thumbColor: Colors.black,
controller: _scrollController,
radius: const Radius.circular(60),
thickness: 6,
child: ListView.builder(
controller: _scrollController,
physics: const NeverScrollableScrollPhysics(),
itemCount: SubjectDetail.listOfSubjects.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return SizedBox(
width: 344,
height: 96,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
child: ListTile(
contentPadding: const EdgeInsets.symmetric(
horizontal: 24, vertical: 8),
title: Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Text(
SubjectDetail
.listOfSubjects[index].name,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700,
fontSize: 15),
),
),
subtitle: Text(
SubjectDetail
.listOfSubjects[index].description,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w400,
fontSize: 10),
),
trailing: Image.asset(SubjectDetail
.listOfSubjects[index].imageUrl),
),
),
);
},
),
),**
const SizedBox(
height: 8,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'General Subjects',
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700,
fontSize: 20,
color: const Color(0xfff3c304)),
),
Text(
'*select one subject',
style: GoogleFonts.openSans(
fontWeight: FontWeight.w300,
fontSize: 14,
color: const Color(0xfff3c304)),
)
],
),
],
),
),
),
)
],
),
),
),
);
I have given same ScrollController object to ListView builder,
RawScrollBar and SingleChildScollView widget.Altough I had given
different ScrollController objects to them

Flutter : Card with Gridview

I'm New to flutter I want to make this design , it take me awhile to find what to use , but ever time i try to code it and use Listview it give me error ,or the card dont aligns to Gridview.
Try below code hope its helpful to you.refer GridView here
Center(
child: GridView.builder(
shrinkWrap: true,
padding: const EdgeInsets.symmetric(horizontal: 30),
itemCount: 4,
itemBuilder: (ctx, i) {
return Card(
child: Container(
height: 290,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20)),
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Image.network(
'https://tech.pelmorex.com/wp-content/uploads/2020/10/flutter.png',
fit: BoxFit.fill,
),
),
Text(
'Title',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Row(
children: [
Text(
'Subtitle',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
],
)
],
),
],
),
),
);
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.0,
crossAxisSpacing: 0.0,
mainAxisSpacing: 5,
mainAxisExtent: 264,
),
),
),
Your result screen->
You can use Gridview and return a Card of your custom style in Gridview Builder I will build your Required Design.
Here is the GridView Official Documentation.
[Documentation1

Flutter click a card from a ListView.builder

I have a screen in my application where I create a bunch of cards from a map using ListView.builder:
Now I want to click on those cards and when I do, I go to a new activity and pass the name of the doctor and the rest of his information to the new activity.
How can I do that?
this is a code sample
class DocBanner extends StatelessWidget {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
child: Text(
'Our Doctors:',
style: TextStyle(
fontSize: 18,
),
),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: 5.0,
vertical: 25.0,
),
height: 190,
width: size.width,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
width: size.width - 150,
child: Card(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'${myList[index]['name']}',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
letterSpacing: 2,
),
),
SizedBox(
height: size.height - (size.height * 0.99),
),
Text(
'${myList[index]['specialite']}',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
height: size.height - (size.height * 0.99),
),
Text(
'${myList[index]['city']}',
style: TextStyle(
fontSize: 20,
color: Colors.red,
),
),
],
),
),
),
);
},
itemCount: myList.length,
),
),
],
);
}
}
You can use a GestureDetector and navigate to another screen in onTap method, like this:
ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return GestureDetector(
onTap: navigateToOtherScreen(myList[index]),
child: Container(
....