Bottom overflowed inside column while listing with Grid.count - flutter

I have problem with column, inside Column i have 3 containers. 1st one has picture inside other two has text. For the first container i want to apply height like 100 for example. but max what can i apply is 60 then it giving bottom overflowed. I am using Grid.count to make grid view and listing them with List.genarate.
PS: Wrapping with expanded effecting first container height, and the container does not have fixed height
Here is my code :
Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
height: 90,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.all(Radius.circular(10)),
boxShadow: [
BoxShadow(
color: Theme.of(context).focusColor.withOpacity(0.9),
blurRadius: 4,
offset: Offset(0, 2)),
],
),
width: 90,
child: Hero(
tag: widget.heroTag + widget.product.id,
child: Padding(
padding: const EdgeInsets.all(6.0),
child: CachedNetworkImage(
height: 90,
fit: BoxFit.fill,
imageUrl: this.widget.product.imageUrl,
placeholder: (context, url) => Image.asset(
'assets/img/loading.gif',
fit: BoxFit.cover,
height: 150,
),
errorWidget: (context, url, error) => Icon(Icons.error),
),
),
),
),
Center(
child: Container(
width: 90,
child: Text(
widget.product.name,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
),
),
Center(
child: Container(
child: Text(
" ${widget.product.salePrice.toString()} Ft ",
style: TextStyle(
color: Colors.blue[800],
fontSize: 13,
fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
)
],
),
Here i am listing them with grid.count and list.genearte :
GridView.count(
scrollDirection: Axis.vertical,
shrinkWrap: true,
primary: false,
mainAxisSpacing: 15.0,
// crossAxisSpacing: 4.0,
padding: EdgeInsets.symmetric(
vertical: 15),
crossAxisCount:
MediaQuery.of(context)
.orientation ==
Orientation.portrait
? 3
: 3,
children: List.generate(
_con.subCategories
.elementAt(0)
.products
.length, (index) {
return ProductGridItemWidget(
heroTag: 'product-grid' +
0.toString() +
index.toString(),
product: _con.subCategories
.elementAt(0)
.products
.elementAt(index),
onPressed: () {
{
_con.addToCart(_con
.subCategories
.elementAt(0)
.products
.elementAt(index));
}
});
}),
)),

Finally found solution from this post
Give a height to the child of GridView
Just need to write this line of code inside GridView.count
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 4),

Related

I Have An Issue In Grid View Builder

without building apk
when i dont build apk in flutter this type of gridview is build
and when i build apk this type of gridveiw list build in flutter
when apk is build
this is my code i want to build an apk so any one can fix this issue
i am getting this issue
while building an app in flutter
otherwise it is ok and give no issue but when i build this app i got error like this is gridview.builder and listview .builder also and i am using scaffold and in body i try everything but nothing work
here is my code
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Select Your City'),
Expanded(child: GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 20),
itemCount: serviceDataList.length,
itemBuilder: (ctx, i) {
// print(serviceDataList);
return GestureDetector(
onTap: () {
setState(() async {
if(isRedundentClick(DateTime.now())){
Fluttertoast.showToast(
msg: "hold on, processing",
toastLength: Toast.LENGTH_SHORT,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0,
);
return;
}else{
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('City_Id', serviceDataList[i]['city_id']);
prefs.setString('City_Name', serviceDataList[i]['city_name']);
prefs.setString('City_Lat', serviceDataList[i]['city_lat']);
prefs.setString('City_Long', serviceDataList[i]['city_long']);
print(serviceDataList[i]['city_id']);
print(serviceDataList[i]['city_name']);
int? rowsEffected2 = await dbHelper?.deletecart();
print(rowsEffected2);
Navigator.push(context, MaterialPageRoute(builder:(context)=>Navigation()));
}
});
},
child: Card(
elevation: 4,
color: Colors.white,
child: Column(
children: [
Container(
height: 210,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20)),
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
child: Stack(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ConstrainedBox(
constraints: new BoxConstraints(
// minHeight: 35.0,
maxHeight: 200.0,
),
child: Expanded(
child: Image.network(
serviceDataList[i]['city_img'] ?? '',
fit: BoxFit.fill,
),
),
),
// Row(
// children: [
// Text(
// 'Subtitle',
// style: TextStyle(
// fontWeight: FontWeight.bold,
// fontSize: 15,
// ),
// ),
// ],
// )
],
),
],
),
),
SizedBox(
height: 35,
child: Container(
color: Colors.grey.shade300,
child: Center(
child: Text(
serviceDataList[i]['city_name'],
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
)
),
);
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.0,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
mainAxisExtent: 264,
),
),)
])))
// bottomNavigationBar:Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// children: [
// SizedBox(
// height: 40,
// width: (MediaQuery.of(context).size.width/1.5),
// child: ElevatedButton(onPressed: (){Navigator.push(context, MaterialPageRoute(builder: (context)=> HomePage()),);
// }, child: Text('Save'))),
// ],
// )
);
pls help me with this code
Avoid wrapping your image within an Expanded widget when the parent is a ConstrainedBox. This is because the parent of the expanded widget cannot be a ConstrainedBox, which is an incorrect use of the parent widget. In debug mode, this will only display a warning, but in release mode, it will not render correctly.
Replace this:
ConstrainedBox(
constraints: new BoxConstraints(
// minHeight: 35.0,
maxHeight: 200.0,
),
child: Expanded(
child: Image.network(
serviceDataList[i]['city_img'] ?? '',
fit: BoxFit.fill,
),
),
),
With this:
ConstrainedBox(
constraints:
new BoxConstraints(
maxHeight: 200.0,
),
child: Image.network(
serviceDataList[i]['city_img'] ?? '',
fit: BoxFit.fill,
),
),

Flutter: Make all screen scrollable with GridView.builder inside

In my home screen my app shows carousel first then a vertical list of challenges cards retrieved from Cloud Firestore using GridView.builder as follows:
GridView.builder(
scrollDirection: Axis.vertical,
itemCount: _challenges.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 4),
),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
if (_challenges[index]["isLocked"] == "true") {
showLockedDialog();
} else {
checkParticipation(index);
if (checkPart == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
ChallengeDetails(_challenges[index])));
}
checkPart = true;
}
},
child: Stack(
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image(
image: NetworkImage(_challenges[index]["image-path"]),
fit: BoxFit.cover,
height: 150,
width: 350,
opacity: _challenges[index]["isLocked"] == "true"
? AlwaysStoppedAnimation(.4)
: null,
),
),
),
Center(
child: Text(
"${_challenges[index]["name"]}\n",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
Center(
child: Text(
"\n${_challenges[index]["date"]}",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
textDirection: TextDirection.ltr,
)),
Center(
child: SizedBox(
height: 130,
width: 130,
child: _challenges[index]["isLocked"] == "true"
? Image.asset("assets/lock-icon.jpg")
: null,
),
)
],
),
);
});
Everything retrieving fine and it is rendered in my home_screen as follows:
body: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(right: 8, left: 8, bottom: 5),
child: Row(
children: [
Text(
AppLocalizations.of(context)!.challenges + " ",
style: TextStyle(fontSize: 20),
),
Text(
AppLocalizations.of(context)!.clickToParticipate,
style: TextStyle(fontSize: 15),
)
],
),
),
Expanded(child: ChallengeCard()),
],
),
The problem is that only the GridView area is scrolling and what am seeking for is to scroll the whole screen with the GridView area, I was trying to use the CustomScrollView() but its not working properly.
I'll be thankful for any help.
First in your GridView.builder add these:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
...
)
then in your home_screen wrap your column with SingleChildScrollView:
SingleChildScrollView(
child: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
...
),
),
You can provide physics: NeverScrollableScrollPhysics() on GridView to disable scroll effect. If you want scrollable as secondary widget use primary: false, to have Full Page scrollable, you can use body:SingleChildScrollView(..) or better using body:CustomScrollView(..)

two streambuilders gives me RangeError (index): Invalid value: Only valid value is 0: 1 when it supposed to read two docs from 2 different collections

What im trying to do is filling a card with the necessary data it needs which is userImage and UserFirstname from my users collection and also data from my subcollection(carReviews)in my carInfo collection where i store the necessary review data:
subcollection(carReviews)
users collection
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('carInfo')
.doc(snapshot.data!.docs[index]
.get('CaradvId'))
.collection('carReviews')
.snapshots(),
builder: (context, snapshot5) {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.where('uid',
isEqualTo: snapshot5
.data!.docs[index]
.get('reviewerId'))
.snapshots(),
builder: (context, snapshot6) {
return Container(
padding: EdgeInsets.symmetric(
horizontal: 5),
height: MediaQuery.of(context)
.size
.height *
0.225,
child: ListView.builder(
shrinkWrap: true,
scrollDirection:
Axis.horizontal,
itemCount: snapshot5
.data!.docs.length,
itemBuilder:
(BuildContext context,
int index) {
DateTime date = snapshot5
.data!.docs[index]
.get('reviewDate')
.toDate();
String dateString =
DateFormat(
'dd MMM yyyy')
.format(date);
return ConstrainedBox(
When i print snapshot5.data!.docs[index].get('reviewerId') i get the two ids who has reviewed which what is expected however the snapshot6.data!.docs.length is 1 which doesn't make any sense!
I have tried using both snapshot6.data!.docs.length & snapshot5.data!.docs.length for the itemcount if i use snapshot6.data!.docs.length i get just one item in list with no errors and if i use snapshot5.data!.docs.length i get range error because it goes through all reviews which are just 2. Me using "hasdata" if statment wont change the output i have tried.
how it looks when i use snapshot5.data!.docs.length
how it looks when i use snapshot6.data!.docs.length
Card(
elevation: 2,
child: Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment
.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.start,
children: [
Container(
padding: EdgeInsets.only(
left:
12.5,
top:
12.5),
height:
55,
width:
55,
child:
CircleAvatar(
backgroundImage:
NetworkImage(
snapshot6.data!.docs[index].get('userImage'),
), //userimage
radius:
40,
),
),
Container(
padding: EdgeInsets.only(
top:
15),
child:
Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Container( padding: EdgeInsets.only(
left:
5),child:
RatingBar.builder(
initialRating: double.parse(snapshot5.data!.docs[index].get('reviewRating')),
minRating: 1,
direction: Axis.horizontal,
allowHalfRating: true,
updateOnDrag: false,
itemCount: 5,
itemSize: 14,
itemPadding: EdgeInsets.symmetric(vertical: 0),
itemBuilder: (context, _) => Icon(
Icons.star,
color: Colors.amber,
),
onRatingUpdate: (rating) {
print(rating);
},
),
),
SizedBox(height: 7.5),
Row(
children: [
Container(
padding: EdgeInsets.only(
left: 7.5,
),
child: Text(
snapshot6.data!.docs[index].get('userFirstname'),
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w800,
color: Colors.black87,
),
),
),
Container(
padding: EdgeInsets.only(left: 2.5),
child: Text(
dateString,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w800,
color: Colors.black54,
),
))
],
)
],
)),
],
),
Container( padding: EdgeInsets.only(
left:
12.5,
top:
12.5),
height: 130,width: MediaQuery.of(
context)
.size
.width *
0.75,
child: Text(snapshot5
.data!
.docs[
index]
.get(
'reviewContent')),
)
],
),
)),

Why is Gridview.count not filling out the space with my dynamic content

I am trying to create a gridview starting from the second column. The first card is just a static card with a button in it. So the second card starting should be dynamic.
All the cards have the same width and height. So basically they all should look like the first card (Add a new dog)
But it's not filling out the space as I expected it would.
Here is part of my code from the body section:
body: Stack(fit: StackFit.expand, children: [
//bg image
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(Images.bgYellow), fit: BoxFit.cover)),
),
//content
SafeArea(
bottom: false,
left: true,
right: true,
top: false,
child: Padding(
padding: EdgeInsets.all(3 * SizeConfig.safeBlockHorizontal),
child: GridView.count(
crossAxisCount: 2,
children: [
//add card
Container(
margin: EdgeInsets.symmetric(
vertical: 1 * SizeConfig.blockSizeVertical,
horizontal: 2 * SizeConfig.blockSizeHorizontal),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 8,
offset: Offset(
0, 2), // changes position of shadow
),
],
),
child: FlatButton(
onPressed: null,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
const IconData(0xe901,
fontFamily: 'icDog'),
color: muddyBrown,
size: 20 * SizeConfig.safeBlockHorizontal,
),
SizedBox(height: 5),
Text(
"ADD A NEW DOG",
style: TextStyle(
color: muddyBrown,
fontWeight: FontWeight.bold,
fontSize: 4 *
SizeConfig.safeBlockHorizontal),
)
],
)),
),
//dynamic content
StateBuilder<PetState>(
observe: () => _petStateRM,
builder: (context, model) {
return Column(
children: [
...model.state.pets.map((pet) =>
GestureDetector(
onTap: () {
Navigator.pushNamed(
context, petDetailRoute);
},
child: Container(
margin: EdgeInsets.symmetric(
vertical: 1 *
SizeConfig
.blockSizeVertical,
horizontal: 2 *
SizeConfig
.blockSizeHorizontal),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(30),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey
.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 8,
offset: Offset(0,
2), // changes position of shadow
),
],
),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
//dynamic data => Photo + Name
children: [
Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
color:
const Color(0xff7c94b6),
image: new DecorationImage(
image: new NetworkImage(
"${pet.photo}"),
fit: BoxFit.cover,
),
borderRadius:
new BorderRadius.all(
new Radius.circular(
50.0)),
border: new Border.all(
color: muddyBrown,
width: 4.0,
),
),
),
SizedBox(height: 5),
Text(
"${pet.name}",
style: TextStyle(
fontSize: 4 *
SizeConfig
.safeBlockHorizontal,
color: muddyBrown,
fontWeight:
FontWeight.bold),
)
],
),
),
))
],
);
}),
],
)
)),
]));
What about simply adding the 'static' card to the 'dynamic' ones and then build one GridView with all of them together?
Widget newDogButton = Card(...);
//dynamic content
StateBuilder<PetState>(
observe: () => _petStateRM,
builder: (context, model) {
return Column(
children: [
newDogButton,
...model.state.pets.map((pet) => // ...
That should take care of most of your layout issues automatically.
Because StateBuilder return a widget. How about moving the Whole GridView inside it?
...
child: Padding(
padding: EdgeInsets.all(3 * SizeConfig.safeBlockHorizontal),
child: StateBuilder<PetState>(
observe: () => _petStateRM,
builder: (context, model) {
return GridView.count(
crossAxisCount: 2,
children: [
// The button "ADD A NEW DOG" here,
Container(...),
//dynamic content here
...model.state.pets.map((pet) =>
...
).toList(),
},
),
),
Every grid item in GridView will have same height and width, if you want different dynamic height or width for different items, use flutter_staggered_grid_view, in your case:
StaggeredGridView.countBuilder(
crossAxisCount: 2,
itemCount: 2,
itemBuilder: (BuildContext context, int index) => new Container(
color: Colors.green,
child: new Center(
child: new CircleAvatar(
backgroundColor: Colors.white,
child: new Text('$index'),
),
)),
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(1, index.isEven ? 2 : 1),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
)
The situation:
To me, this problem is not coming from your Dynamic content but from the height allowed to it to display it's content. Inside the GridView.count constructor, the default childAspectRatio value is 1.0, meaning that the default max height of each child of the GridView is deviceWidth / crossAxisCount (2 in your case).
The problem:
In order for each child to display correctly, it's height must not exceed this ratio (causing your overflowed error).
My opinion:
To solve this problem, I will either replace the dynamic content StateBuilder<PetState> with a static Widget which height will not exceed the ratio OR wrap the dynamic content StateBuilder<PetState> in a SingleChildScrollView to ensure that the overflowed error will not happen and the wrapper can produce the scroll effect to see the entire dynamic content.

How to add space between words on separate lines in Flutter?

I want to add space between "Radio Frequency" and "Propagation" vertically i.e something like margin. and also make sure that text does not cut from top or bottom if I increase the font size.
Below is my code, I tried with spacing of letters, words and also decoration param but it did not get desired results. Thank you for your patience :)
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.count(
padding: const EdgeInsets.fromLTRB(0, 20, 0, 0),
childAspectRatio: 1.5,
mainAxisSpacing: 30,
crossAxisCount: 3,
children: List.generate(
12,
(index) {
return Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 5),
child: CircleAvatar(
child: Transform.scale(
scale: 1,
child: Image.asset(
'assets/icons/radar_icon.png',
height: 30,
width: 30,
fit: BoxFit.fitWidth,
),
),
backgroundColor: Colors.grey.shade300,
radius: 30,
)),
Flexible(
child: Text(
"Radio Frequency Propagation",
textAlign: TextAlign.center,
style: GoogleFonts.roboto(color: Colors.black87, fontSize: 14,height: 0.8),
),
),
],
));
},
),
));
}
You are using height is correct. But I think the problem is the placement of the style parameters.
It should be like this:
Flexible(
child: Text(
"Radio Frequency \nPropagation",
textAlign: TextAlign.center,
style: GoogleFonts.roboto(
textStyle: TextStyle(
color: Colors.black87,
fontSize: 14,
height: 1.5,
),
),
),
);
}