How to align text and image in a SliverGrid in Flutter? - flutter

I am using the SliverGrid feature to build my gridView. I trying to have the text placed below the image but the text isn't aligning with the image and its showing a Bottom Overflowed error. This is the code:
SliverPadding(
padding: const EdgeInsets.only(left: 8, right: 8),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int i) {
return GestureDetector(
onTap: () {},
child: Column(
children: <Widget>[
GridTile(
child: Image.network(
'https://images.unsplash.com/photo-1562176566-73c303ac1617?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80',
fit: BoxFit.cover,
),
),
Text(
'Sammy the Pup',
style: khomeStyle.copyWith(
color: kOrange, fontSize: 14),
),
],
),
);
},
childCount: 200,
),
),
),
And this is what the gridview looks like(Output of the above):
And this is what I want to achieve:

The height of GridView is determined by the AspectRatio
SliverGridDelegateWithFixedCrossAxisCount(
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
crossAxisCount: 2,
childAspectRatio: 1 / 1,<---
),
As the AspectRatio gets smaller the height gets larger and as the ratio gets larger the heights gets smaller

Related

GridView grid delegate display grids the same on all devices

I used gridView.builder. To set the size of the grid, I use MediaQuery, but for some reason the gridView is displayed differently on different devices, using which parameter in gridDelegate: can I fix this?
my gridView code:
Widget buildCatalog(List<Product> product) => CustomScrollView(
controller: sController,
slivers: [
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// mainAxisExtent: ,
maxCrossAxisExtent: 300,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.3),
crossAxisSpacing: 10,
mainAxisSpacing: 10),
delegate: SliverChildBuilderDelegate(childCount: product.length,
(BuildContext context, int index) {
return GestureDetector(
onTap: () {},
child: Container(
padding: const EdgeInsets.only(left: 2, right: 2, top: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8)),
child: Column(
children: <Widget>[
InkWell(
child: Container(
margin: const EdgeInsets.only(top: 5),
child: Image.network(),
),
),
const SizedBox(
height: 10,
),
Text(),
// Spacer(),
const SizedBox(height: 8),
Text(),
const SizedBox(height: 5),
buildButton(index, productItem.id),
],
),
),
);
}),
),
]
);
This is my grid on big displays:
and this on small displays:
The solution was flutter_screenutil package

Flutter: FlexLayoutManager similar to the one in native android

So I'm trying to implement a flex listview similar to the google FlexLayoutManager to the horizontal axis with wrap, you can see an example in the wrap section
https://github.com/google/flexbox-layout/raw/main/assets/flex-wrap.gif
here is my code:
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
padding: EdgeInsetsDirectional.only(start: 16, end: 12),
itemBuilder: (context, index) {
return InkWell(
onTap: (){
},
child: Container(
height: 24,
alignment: Alignment.center,
child: Text(
categories[index].name,
),
),
);
},
)
what I have to add to my listview to make the items wrap and move to the next row if they exceeded the screen width?
Not tested, but as I indicated in my comment, I'd use something like:
Wrap(
children: [
for (final c in categories)
InkWell(child: Text(c.name)),
]);
adding of course all your parameters, and the extra container.
As an alternative, you can use a GridView.builder instead of ListView.builder:
Creates a scrollable, 2D array of widgets that are created on demand.
result:
I have made my window very small and the children still wrap:
With the window maximized:
code:
GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: _categories.length,
padding: EdgeInsetsDirectional.only(start: 16, end: 12),
itemBuilder: (context, index) {
return InkWell(
onTap: () {},
child: Container(
height: 24,
alignment: Alignment.center,
child: Text(
categories[index].name,
),
),
);
},
)

How to place the items 3 per row in Flutter

I have a list with 20 items in a list (dynamic not fixed). I want to display these items in a container with 3 or 4 items per row.
At present I am getting the attached output.
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(itemList.length,
(index) {
return Wrap(
children: <Widget>[
Container(
//height:140,
child: SizedBox(
width: 100.0,
height: 50.0,
child: Card(
color: Colors.white,
semanticContainer: true,
clipBehavior:
Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10.0),
),
elevation: 5,
margin: EdgeInsets.all(10),
child: Center(
child: Text(
(itemList.length[index]
.toUpperCase()),
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
),
),
),
)),
],
);
}),
),
You can achieve this using a widget called GridView.builder. Check the code below for how to use a gridview widget:
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// number of items per row
crossAxisCount: 3,
// vertical spacing between the items
mainAxisSpacing: 10,
// horizontal spacing between the items
crossAxisSpacing: 10,
),
// number of items in your list
itemCount: 20
),
To read more on the GridView widget, check the link below:
GridView Widget in Flutter
I hope this helps.
Use a GridView.
GridView.builder(
scrollDirection: Axis.vertical,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
)
Using a GridView works for me.
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4 //How many items do you want to show,
mainAxisSpacing: 10 //Space between the lines,
crossAxisSpacing: 10 //Space between the items,
),

Problem with Image resizing inside Column Widget in Flutter

I have the following code snippet,
GridTile(
child: Card(
elevation: 5,
child: Image.network(imageUrl, fit: BoxFit.scaleDown,),
),
),
);
producing following output..
But when I add column to my card like this...
GridTile(
child: Card(
elevation: 5,
child: Column(
children: <Widget>[
Image.network(imageUrl, fit: BoxFit.scaleDown,),
],
),
),
);
I got the below overflow issue..
What am I missing here., Is there any important layout details about Column that I need to take care of. I need column so that I can add favorite button and product description below the image. Find below the parent widget for reference.
return Scaffold(
appBar: AppBar(
title: Text('Shopify'),
),
body: GridView.builder(
itemBuilder: (context, index) => ProductItem(dummyProducts[index].title, dummyProducts[index].imageUrl),
itemCount: dummyProducts.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10
),
),
);
Your images have a determined proportion (width / height ratio).
Using gridDelegate with childAspectRatio you can assign the ratio of the GridTile inside your GridView.
Adjust the childAspectRatio or adjust the images ratio.
Play with this number to see the effect:
childAspectRatio: 1 // square
childAspectRatio: 2 // horizontal rectangle
childAspectRatio: 0.5 // vertical rectangle
Enclosing the image in AspectRatio finally did the trick. Please find the code below.
GridTile(
child: Card(
elevation: 5,
child: Column(
children: <Widget>[
AspectRatio(
aspectRatio: 1,
child: Image.network(imageUrl, fit: BoxFit.scaleDown,),
),
],
),
),
);

How to display text in a dynamic GridView when a button is pressed?

I want to display text in a dynamic gridview and when a button is pressed its value should be displayed in that textview inside the gridview.
child: GridView.count(
crossAxisCount: 7,
childAspectRatio: 1,
padding: const EdgeInsets.all(10.0),
mainAxisSpacing: 15.0,
crossAxisSpacing: 15.0,
children: wordList.map((String data) {
return Card(
color: Colors.teal,
child: Text("",
textAlign: TextAlign.center,
),
);
}).toList(),
)