How to set grid view column height? - flutter

I am new to flutter and don't have much experience.
I am trying to develop an android app using flutter and this is my previous app design.
And I'm also able to successfully make grid view in flutter but the column height is the problem. Is their anyone who can help me with my flutter code.
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
hi(){
}
return new Scaffold(
appBar: new AppBar(
actions: <Widget>[],
title: new Text("milla"),
),
body: new Container(
child: new Center(
child: new GridView.count(
shrinkWrap: true,
scrollDirection: Axis.vertical,
childAspectRatio:1.0,
crossAxisCount: MediaQuery.of(context).size.width <= 400.0 ? 3 : MediaQuery.of(context).size.width >= 1000.0 ? 5 : 4,
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this would produce 2 rows.
crossAxisSpacing: 2.0,
// Generate 100 Widgets that display their index in the List
children: new List.generate(100, (index) {
return new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
verticalDirection: VerticalDirection.down,
children: <Widget>[
new Center(
child: new Image(
image: new NetworkImage('https://github.com/flutter/website/blob/master/_includes/code/layout/lakes/images/lake.jpg?raw=true')
)
),
new Expanded(child: new Text("apple2")), new Expanded(child: new Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
)),new Expanded(child: new Center(child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[new Text("+",style: new TextStyle(fontSize: 24.0),),new Text("1"),new Text("-")])))]
);
}),
),
),
)
);
}
}
And this is my output.
How to set column height?
When i'm trying to add new view, it's showing this error "Another exception was thrown: A RenderFlex overflowed by 21 pixels on the bottom."

Put this instead of
childAspectRatio:1.0 to childAspectRatio: (itemWidth / itemHeight)
var size = MediaQuery.of(context).size;
final double itemHeight = (size.height) / 2;
final double itemWidth = size.width / 2;
It works fine in my code to set height and width of Gridview

You might try this:
GridView.count(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.height / 400,
children: <Widget>[...]
);

Try this
childAspectRatio: mediaQueryData.size.height / 1000,
where
MediaQueryData mediaQueryData = MediaQuery.of(context);
I saw this code somewhere and looks ok to me.

Maintain
childAspectRatio: with MediaQuery.of(context).size.height/600
if this didint work change 600 with diffrent but less numbers.

[Screenshot][https://i.stack.imgur.com/h28C2.png]1
This is my code:
final screenWidth = MediaQuery.of(context).size.width/3;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new Container(
color: Colors.white70,
padding: EdgeInsets.all(5.0),
child: new GridView.count(
childAspectRatio: screenWidth/180.0,
crossAxisCount: 3,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0,
children: _buildFirdTitles(35),
),
),
);

If you use GridView.builder
Try this, use gridDelegate section to custom items height
Edit the parameter childAspectRatio
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
// width / height: fixed for *all* items
childAspectRatio: 0.75,
)
class ItemCardGridView extends StatelessWidget {
const ItemCardGridView(
{Key? key,
required this.crossAxisCount,
required this.padding,
required this.items})
// we plan to use this with 1 or 2 columns only
: assert(crossAxisCount == 1 || crossAxisCount == 2),
super(key: key);
final int crossAxisCount;
final EdgeInsets padding;
// list representing the data for all items
final List<ItemCardData> items;
#override
Widget build(BuildContext context) {
return GridView.builder(
padding: padding,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
// width / height: fixed for *all* items
childAspectRatio: 0.75,
),
// return a custom ItemCard
itemBuilder: (context, i) => ItemCard(data: items[i]),
itemCount: items.length,
);
}
}

Related

Flutter Card child content height is larger than its parent

I'm trying to use a GridView to handle displays for multiple Card, each Card contains of an Image. Unfortunately it turns out that the Image is taking a larger height than its parent (see attached picture for the details).
I'm pretty new to Flutter layout so any ideas why this is happening and how I can resolve this? I want the layout to be something like this:
Display 2 cards on each line.
The Card width or height should not be fixed.
The Image height should be scaled according to its width.
class SquadSelectionScreen extends StatelessWidget {
final List<Team> teams;
const SquadSelectionScreen({super.key, required this.teams});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Squads'),
),
body: GridView.count(
crossAxisSpacing: 10,
crossAxisCount: 2,
padding: const EdgeInsets.all(16),
children: teams
.map(
(team) => SquadView(team: team),
)
.toList(),
),
);
}
}
class SquadView extends StatelessWidget {
final Team team;
const SquadView({super.key, required this.team});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
context.push('/squads/${team.code}');
},
child: Card(
elevation: 1,
child: Column(
children: [
Image(
image: NetworkImage(team.imageUrl),
),
const SizedBox(
height: 8,
),
Center(
child: Text(team.name),
),
],
),
),
);
}
}
Using GridView.count has a very visible drawback, namely the size of the aspect ratio of the grid will always be one (1:1 or Square) and can't be changed.
So if you look at the code above, you can't set an image with the same aspect ratio because the text will sink.
The first suggestion for me if you still want to use GridView.count is
Wrapping your Image with AspectRatio that has value higher than one (example set Ratio to 4/3, 5/3, 16/9, or landscape looks). Note: 4/3 = is higher than 1, 16/9 = is higher than 1, etc..
Then wrap the Text Widget with Expanded()
Example code:
class SquadView extends StatelessWidget {
final Team team;
const SquadView({super.key, required this.team});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Card(
elevation: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
AspectRatio(
aspectRatio: 4/3, // you can set the value to 16/9 or anything that result is higher than one
child: Image(
image: NetworkImage(team.imageUrl),
fit: BoxFit.cover, // set How the image looks to Fit
),
),
const SizedBox(
height: 8,
),
Expanded(
child: Center(
child: Text(team.name, overflow: TextOverflow.ellipsis),
),
),
],
),
),
),
);
}
}
I suggest you try GridView.builder or another GridView. You can look at the documentation here
or this third package this will be good for to try flutter_staggered_grid_view. The flutter_staggered_grid_view is more flexible to create GridView with various size.

how to set limit max widget in row flutter

I have controller generated like this
final inputs = List.generate(100, (i) => TextEditingController());
and the input inside row
Row: (
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 3),
child: TextField(
autocorrect: false,
controller: inputs[1], <= here is controller define
)),
]);
if I use for loop then row input become 100 in single row
I want max 5 input in one row
Here is screenshot
how to achieve this
thank you
Try with GridView
GridView.count(
crossAxisCount: 5,
crossAxisSpacing: 4.0,
mainAxisSpacing: 8.0,
children: List.generate(inputs.length, (index) {
return Center(
child: ,// your widget
);
}
)

if statement in ListView flutter

I'm trying to have a responsive drawer that when the screen size is higher than X itemExtent is set to default, how could I add a if statement inside a ListView?
Widget drawer(context){
double _containerHeight = MediaQuery. of(context). size. height;
int _numberOfListTiles = 16;
return new Drawer(
child: Container(
height: _containerHeight,
color: const Color(0xff68778d),
child: ListView(
padding: EdgeInsets.zero,
itemExtent: _containerHeight/_numberOfListTiles,
children: [
],
),
)
);
}
I would like to do:
if(_containerHeight < 700){
itemExtent: _containerHeight/_numberOfListTiles,
}
The cleanest way (in my opinion) would be to instantiate your variable at the top of your drawer method as you did for the _containerHieght and _numberOfListTiles variables.
Your code would then look like that
Widget drawer(context) {
final double _containerHeight = MediaQuery.of(context).size.height;
final int _numberOfListTiles = 16;
double itemExtent;
if(_containerHeight < 700){
itemExtent = _containerHeight/_numberOfListTiles;
} else {
itemExtent = 100; // Default ?
}
return new Drawer(
child: Container(
height: _containerHeight,
color: const Color(0xff68778d),
child: ListView(
padding: EdgeInsets.zero,
itemExtent: _containerHeight / _numberOfListTiles,
children: [],
),
));
}

Flutter GridView.builder is Generating Unwanted Extra Space

I am trying to display a row of buttons. Since the number of buttons depends on the number of elements in a List, I have to use GridView.builder to dynamically create the right amount of buttons. Unfortunately it seems that GridView.builder is taking up alot of unnecessary space. Anyone know what is wrong here?
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Dice buttons
Flexible(
child: GridView.builder(
itemCount: dices.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: dices.length,
),
itemBuilder: (BuildContext context, int index) {
return new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ButtonTheme(
minWidth: 50.0,
height: 50.0,
child: RaisedButton(
child: Text(
dices[index].toString(),
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
color: usedDices[index] || !expectNum
? Colors.grey
: Colors.black,
onPressed: () {
if (!usedDices[index] && expectNum) {
setState(() {
numUsed[turn] = dices[index].toString();
numUsedIndex[turn] = index;
});
expectNum = false;
usedDices[index] = true;
}
},
),
),
]);
})),
Link to Pic: https://drive.google.com/file/d/1_Jr4rz9GJ-D8-Xjxs2w8Sn8lOdnBBqTc/view?usp=sharing
As you can see are lots of unnecessary space here and it seems to be the reuslt of GridView.builder
That space is the result of Flexible, which fills the available space. You will see that if you replace it with a Container and give it a height, it won't produce that much space below.
Just had this problem, top SliverPadding is set to 20.0 by default. Looking at docs I see:
/// By default, [ListView] will automatically pad the list's scrollable
/// extremities to avoid partial obstructions indicated by [MediaQuery]'s
/// padding. To avoid this behavior, override with a zero [padding] property.
So,
GridView.builder(
// shrinkWrap: true,
padding: EdgeInsets.zero,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 1,
mainAxisSpacing: 1,
crossAxisCount: 3,
),
itemBuilder: (context, index) {
return Container(
color: Colors.black,
);
},
itemCount: 10,
),
or
If you put a widget before the ListView, you should wrap the ListView with a
MediaQuery.removePadding widget (with removeTop: true)

'Wrap' widget - items alignment

Is there a way to align Wrap widget items in all lines except the last with spaceAround and the last one with start? Is there another way to do it? Number of rows and columns should not be fixed - it depends on device width and height.
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SingleChildScrollView(
child: new Wrap(
direction: Axis.horizontal,
spacing: 10.0,
alignment: WrapAlignment.spaceAround,
children: <Widget>[
//items
],
),
);
});
See screenshot how it actually looks like. I need the last row to have the same spacing as the others and start from the left.
AFAIK there's no way to achieve this with Wrap widget, but similar effect produce GridView with extent constructor:
GridView.extent(
children: List.generate(10, (index) {
return Center(
child: Icon(
Icons.star_border,
size: 100.0,
),
);
}),
maxCrossAxisExtent: 150.0,
)
If the size of the item is known, it can be achieved in this way:
const itemCount = 10;
const itemSize = 100.0;
LayoutBuilder(
builder: (context, c) {
const spacing = 0.0;
final columnCount =
((c.maxWidth + spacing) / (itemSize + spacing)).floor();
final rowCount = (itemCount / columnCount).ceil();
final maxLength = columnCount * rowCount;
return Wrap(
spacing: spacing,
children: List.generate(
math.max(itemCount, maxLength),
(index) => index < itemCount
? _buildItem(context, index)
: const SizedBox(width: itemSize, height: itemSize),
),
);
},
);