GridView height fit the children height flutter - flutter

I'm confuse about the usage of gridview in flutter.
I want to display a list of features with their rates.
The feature component/widget isn't that big in term of height but when I place them in a gridview the height of each case is way more bigger that it needs to be.
How can I control the height of each case to fit the child height ?
here is my code :
import 'package:flutter/material.dart';
import 'package:project/Components/ReviewComps/AttributeRatings.dart';
class ReviewPage extends StatelessWidget {
const ReviewPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: const <Widget>[
AttributeRatings(),
],
),
),
));
}
}
here is my gridview that create problems :
import 'package:flutter/material.dart';
class AttributeRatings extends StatelessWidget {
const AttributeRatings({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
var featureList = [
_featureItems(4),
_featureItems(3.2),
_featureItems(1),
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("Features average rating"),
GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 20,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
children: featureList,
),
],
);
}
}
Container _featureItems(double rate) {
return Container(
color: Colors.red,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Feature'),
Text(rate.toString()),
],
),
Stack(
children: [
Container(
height: 2,
width: double.infinity,
color: const Color(0xffDBDFED),
),
FractionallySizedBox(
widthFactor: rate / 5,
child: Container(
height: 2,
color: const Color(0xff39B0EA),
),
)
],
)
],
),
);
}

You can give childAspectRatio to customise a height as following
import 'package:flutter/material.dart';
class AttributeRatings extends StatelessWidget {
const AttributeRatings({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
var featureList = [
_featureItems(4),
_featureItems(3.2),
_featureItems(1),
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("Features average rating"),
GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 20,
childAspectRatio: 4,//You may have to calculate based on screen size
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
children: featureList,
),
],
);
}
}
Container _featureItems(double rate) {
return Container(
color: Colors.red,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Feature'),
Text(rate.toString()),
],
),
Stack(
children: [
Container(
height: 2,
width: double.infinity,
color: const Color(0xffDBDFED),
),
FractionallySizedBox(
widthFactor: rate / 5,
child: Container(
height: 2,
color: const Color(0xff39B0EA),
),
)
],
)
],
),
);
}

The solution I found is quite complicated but I changed the gridview to a list view and put rows inside. The most dificult was to work with odd lengths lists here is my solution :
import 'package:flutter/material.dart';
class AttributeRatings extends StatelessWidget {
const AttributeRatings({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
var featureList = [4, 3.2, 4, 2, 3.2];
double nbRows = featureList.length % 2 == 0
? (featureList.length / 2)
: (featureList.length / 2) + 1;
var reworkedFeatureList = [];
if (featureList.length % 2 == 0) {
for (var i = 0; i < (featureList.length - 1) / 2; i++) {
reworkedFeatureList.add([featureList[i * 2], featureList[(i * 2) + 1]]);
}
} else {
final retVal = featureList.removeLast();
for (var i = 0; i < (featureList.length - 1) / 2; i++) {
reworkedFeatureList.add([featureList[i * 2], featureList[(i * 2) + 1]]);
}
reworkedFeatureList.add([retVal, -1]);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("Features average rating"),
ListView.separated(
separatorBuilder: (context, index) {
return const SizedBox(height: 12);
},
itemCount: nbRows.toInt(),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) =>
_featureItemsRow(reworkedFeatureList[index]),
),
],
);
}
}
Row _featureItemsRow(var rates) {
return Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 10.0),
child: _featureItem(rates[0].toDouble()),
)),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: _featureItem(rates[1].toDouble()),
)),
],
);
}
Column _featureItem(double rate) {
if (rate == -1) {
return Column();
} else {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Feature'),
Text(rate.toString()),
],
),
Stack(
children: [
Container(
height: 2,
width: double.infinity,
color: const Color(0xffDBDFED),
),
FractionallySizedBox(
widthFactor: rate / 5,
child: Container(
height: 2,
color: const Color(0xff39B0EA),
),
)
],
)
],
);
}
}

Related

Flutter : Horizontally and Vertically Scrolling Time Table with two sided header

In my flutter application I want to create a timetable widget as below which will scroll horizontally and vertically with corresponding heading. The timetable should have 'Day' as horizontal heading and 'Period' as vertical heading. During horizontal scrolling the 'Period' header should freeze and horizontal 'Day' header should scroll with data. Similarly, during vertical scrolling the 'Day' header should freeze and vertical 'Period' header should scroll with data. How can I achieve a widget like that.Please help..
In Android we can obtain the above type of scrolling by extending HorizontalScrollView & VerticalScrollView.
You can archive this using nested listView widgets.
You can try this approach:
class TimeTableView extends StatefulWidget {
const TimeTableView({super.key});
#override
State<TimeTableView> createState() => _TimeTableViewState();
}
class _TimeTableViewState extends State<TimeTableView> {
final periodsSlots = 15;
final double containerHeight = 55.0;
final double containerWidth = 80;
final days = [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
final subjects = [
"Maths",
"Hindi",
"English",
"Chemistry",
"History",
"Geography",
];
late ScrollController mainController;
late ScrollController secondController;
#override
void initState() {
super.initState();
secondController = ScrollController();
mainController = ScrollController()
..addListener(() {
if (mainController.hasClients && secondController.hasClients) {
secondController.jumpTo(mainController.offset);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Time Table"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: PageView(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
// Top header View
SizedBox(
height: containerHeight,
width: containerWidth,
child: CustomPaint(
painter: RectanglePainter(),
child: Stack(
children: const [
Align(
alignment: Alignment.topRight,
child: Padding(
padding: EdgeInsets.all(4.0),
child: Text("Day"),
),
),
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: EdgeInsets.all(4.0),
child: Text("Period"),
),
),
],
),
),
),
Expanded(
child: SizedBox(
height: containerHeight,
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
controller: mainController,
child: Row(
children: List<Widget>.generate(
days.length,
(index) => Container(
height: containerHeight,
width: containerWidth,
color: bgColorHeader(index),
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8),
child: Center(child: Text(days[index])),
),
),
),
),
),
),
)
],
),
SizedBox(
// Added fixed size to scroll listView horizontal
height: 500,
child: ListView.builder(
physics: const ClampingScrollPhysics(),
padding:
EdgeInsets.zero, // remove listview default padding.
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: periodsSlots,
itemBuilder: (context, index) => Container(
height: containerHeight,
width: containerWidth,
color: bgColorHeader(index),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// period header
Padding(
padding: EdgeInsets.zero,
child: SizedBox(
width: containerWidth,
height: containerHeight,
child: Center(child: Text("period ${index + 1}")),
),
),
// period subjects
Expanded(
child: SizedBox(
height: containerHeight,
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
controller: secondController,
child: Row(
children: List<Widget>.generate(
subjects.length,
(index) => Container(
color: Colors.white,
child: Container(
height: containerHeight,
width: containerWidth,
color: bgColorSubject(index),
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4),
child: Text(subjects[index]),
)),
),
),
),
),
),
),
)
],
),
),
),
)
],
),
],
),
),
);
}
// Alternate background colors
Color bgColorHeader(int index) =>
index % 2 == 0 ? Colors.cyan.withOpacity(0.5) : Colors.cyanAccent;
Color bgColorSubject(int index) =>
index % 2 == 0 ? Colors.grey.withOpacity(0.5) : Colors.grey;
}
// Draw cross line from top left container
class RectanglePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final backgroundPaint = Paint()
..color = Colors.cyanAccent
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
final crossLine = Paint()
..color = Colors.white
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
// Draw the rectangle
canvas.drawRect(Offset.zero & size, backgroundPaint);
// Draw the cross line
canvas.drawLine(Offset.zero, Offset(size.width, size.height), crossLine);
//canvas.drawLine(Offset(0, size.height), Offset(size.width, 0), crossLine);
}
#override
bool shouldRepaint(RectanglePainter oldDelegate) => false;
}
Scrolling widgets will create a default scroll controller (ScrollController class) if none is provided. A scroll controller creates a ScrollPosition to manage the state specific to an individual Scrollable widget.
To link our scroll controllers we’ll use linked_scroll_controller, a scroll controller that allows two or more scroll views to be in sync.
import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
class ScrollDemo extends StatefulWidget {
#override
_ScrollDemoState createState() => _ScrollDemoState();
}
class _ScrollDemoState extends State<ScrollDemo> {
final List<String> colEntries = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
final List<String> rowEntries =
Iterable<int>.generate(15).map((e) => e.toString()).toList();
late LinkedScrollControllerGroup _horizontalControllersGroup;
late ScrollController _horizontalController1;
late ScrollController _horizontalController2;
late LinkedScrollControllerGroup _verticalControllersGroup;
late ScrollController _verticalController1;
late ScrollController _verticalController2;
#override
void initState() {
super.initState();
_horizontalControllersGroup = LinkedScrollControllerGroup();
_horizontalController1 = _horizontalControllersGroup.addAndGet();
_horizontalController2 = _horizontalControllersGroup.addAndGet();
_verticalControllersGroup = LinkedScrollControllerGroup();
_verticalController1 = _verticalControllersGroup.addAndGet();
_verticalController2 = _verticalControllersGroup.addAndGet();
}
#override
void dispose() {
_horizontalController1.dispose();
_horizontalController2.dispose();
_verticalController1.dispose();
_verticalController2.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('sync scroll demo'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: 75,
height: 75,
color: Colors.grey[200],
),
const SizedBox(width: 10),
Container(
height: 75,
width: 400,
color: Colors.blue[100],
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: _horizontalController2,
child: HeaderContainer(rowEntries: rowEntries),
),
)
],
),
const SizedBox(height: 10),
Row(
children: <Widget>[
Container(
width: 75,
height: 400,
color: Colors.blue[100],
child: SingleChildScrollView(
controller: _verticalController2,
child: ColumnContainer(
colEntries: colEntries,
),
),
),
const SizedBox(width: 10),
SizedBox(
width: 400,
height: 400,
child: SingleChildScrollView(
controller: _verticalController1,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: _horizontalController1,
child: BodyContainer(
rowEntries: rowEntries,
colEntries: colEntries,
),
),
),
)
],
),
],
),
),
),
);
}
}
class ColumnContainer extends StatelessWidget {
final List<String> colEntries;
const ColumnContainer({
Key? key,
required this.colEntries,
}) : super(key: key);
#override
Widget build(BuildContext context) {
int numberOfRows = colEntries.length;
return Column(
children: List.generate(
numberOfRows,
(i) {
return Container(
height: 75,
width: 75,
decoration: BoxDecoration(border: Border.all(color: Colors.white)),
child: Center(child: Text(colEntries[i])),
);
},
),
);
}
}
class HeaderContainer extends StatelessWidget {
final List<String> rowEntries;
const HeaderContainer({
Key? key,
required this.rowEntries,
}) : super(key: key);
#override
Widget build(BuildContext context) {
int _numberOfColumns = rowEntries.length;
return Row(
children: List.generate(
_numberOfColumns,
(i) {
return Container(
height: 75,
width: 75,
decoration: BoxDecoration(border: Border.all(color: Colors.white)),
child: Center(child: Text(rowEntries[i])),
);
},
),
);
}
}
class BodyContainer extends StatelessWidget {
final List<String> colEntries;
final List<String> rowEntries;
const BodyContainer({
Key? key,
required this.colEntries,
required this.rowEntries,
}) : super(key: key);
#override
Widget build(BuildContext context) {
int _numberOfColumns = rowEntries.length;
int _numberOfLines = colEntries.length;
return Column(
children: List.generate(_numberOfLines, (y) {
return Row(
children: List.generate(_numberOfColumns, (x) {
return TableCell(item: "${colEntries[y]}${rowEntries[x]}");
}),
);
}),
);
}
}
class TableCell extends StatelessWidget {
final String item;
const TableCell({
Key? key,
required this.item,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 75,
width: 75,
decoration: BoxDecoration(border: Border.all(color: Colors.grey)),
child: Center(child: Text(item)),
);
}
}
I found these solutions from these 2 links.
Flutter: How to create linked scroll widgets
Flutter: Creating a two-direction scrolling table with a fixed head and column

How to dynamically handle child aspect ratio in gridview builder flutter

I have a Gridview builder to list items in flutter web. Render flex issue is happening when minimizing screen size. I gave aspect ratio based on screen size. But it is not working as expected. I used layout builder to get screen width.I gave static width but I think its not a good practice.
How to change the aspect ratio dynamically?
class CateGorySellectView extends StatefulWidget {
const CateGorySellectView({Key? key}) : super(key: key);
#override
State<CateGorySellectView> createState() => _CateGorySellectViewState();
}
class _CateGorySellectViewState extends State<CateGorySellectView> {
#override
Widget build(BuildContext conText) {
return Scaffold(
body: Center(
child: Row(
children: [
Expanded(
flex: 3,
child: Container(
child: Padding(
padding: const EdgeInsets.only(left: 80.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(right: 300.0),
child: LayoutBuilder(builder: (context, constraints) {
var parentWidth = constraints.maxWidth;
return GridView.builder(
itemCount: areaOfintrest.length,
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: parentWidth < 600 ? 3 : 5,
childAspectRatio: parentWidth < 350
? 300 / 250
: parentWidth < 700
? 200 / 150
: parentWidth < 800
? 200 / 170
: 180 / 87,
crossAxisSpacing: 7),
itemBuilder: (_, index) {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: Obx(() {
return Padding(
padding: const EdgeInsets.only(
right: 0, top: 8),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: AppColors.primaryColor)),
child: Stack(
children: [
Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Padding(
padding:
const EdgeInsets.only(
top: 4.0),
child: AutoSizeText(
areaOfintrest[index]
.toJson()[
'tag_display_name'],
textAlign: TextAlign.center,
),
)
],
)),
],
),
),
);
}),
);
});
}),
)
],
),
),
)),
],
)),
);
}
}

GridView.builder // Items are overflowing

Problem: I want to use widget in my gridview builder, but the items in the grid keep overflowing.
Image (Code below):
Code:
This is the GriView.builder:
return Expanded(
child: GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
padding: EdgeInsets.symmetric(
horizontal: 27.w,
),
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
itemCount:
Provider.of<MainElementList>(context).lookbackList.length,
//
itemBuilder: (context, index) {
return HistoryThumb(
index: index + 1,
usedFrom: 'lookbackScreen',
);
}),
This is HistoryThumb, the widget that is dispalyed in the grid:
return Column(
children: [
//THIS IS THE CARD WITH THE DATE
HistoryThumbHeader(displayDate: displayDate, usedFrom: usedFrom),
//
SizedBox(
height: usedFrom == 'homeScreen' ? 7.h : 12.h,
),
GestureDetector(
onTap: () {
//irrelevant
},
//THIS IS THE RECTANGLE
child: ClipRRect(
borderRadius: BorderRadius.circular(8.r),
child: Container(
padding: EdgeInsets.all(0),
height: historyThumbSize,
width: historyThumbSize,
color: Provider.of<MainElementList>(context).allTasksDone(index)
? customColorScheme['Shade 2']
: customColorScheme['Shade 1'],
//
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//irrelevant
],
),
),
),
),
],
);
What the design is supposed to look like in the end:
I got it. For posterity, I needed to manually set the child aspect ratio. Code:
return Expanded(
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, childAspectRatio: 0.689),
padding: EdgeInsets.symmetric(
horizontal: 27.w,
),
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
itemCount:
Provider.of<MainElementList>(context).lookbackList.length,
//
itemBuilder: (context, index) {
return HistoryThumb(
index: index + 1,
usedFrom: 'lookbackScreen',
);
}),
Try using a Gridtile and a list.generator . The gridtile displays a header with the date time. The header overlaps the card so padding of 100 moves the column down. The column is center horizontally and vertically. I expanded the mylist by index value to be 100 pixels in height and infinite on the width. Next I add a row with two text values: left side and right side and expand the row and stretch and evenly space the children. You must set the aspect ratio to adjust the size of the gridtile
class Test_Gridview extends StatefulWidget {
Test_Gridview({Key? key}) : super(key: key);
#override
State<Test_Gridview> createState() => _Test_GridviewState();
}
List<String> myList=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','v','x','y','z'];
class _Test_GridviewState extends State<Test_Gridview> {
var _crossAxisSpacing = 8;
var _screenWidth = MediaQuery.of(context).size.width;
var _crossAxisCount = 3;
var _width = (_screenWidth - ((_crossAxisCount - 1) * _crossAxisSpacing)) /
_crossAxisCount;
var cellHeight = 600;
var _aspectRatio = _width / cellHeight;
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(
title: const Text('GridView'),
),
body: GridView.count(
crossAxisCount: 2,
childAspectRatio: _aspectRatio,
children: List.generate(myList.length, (index) {
return GridTile(
header: GridTileBar(title:Text(DateTime.now().toString()),backgroundColor: Colors.red,),
child:Card(
child:SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 100.0),
child:Column(
crossAxisAlignment: CrossAxisAlignment.center ,
mainAxisAlignment: MainAxisAlignment.center,
children:[
Container(color:Colors.yellow,width:double.infinity,height:100,child: Text(myList[index],textAlign:TextAlign.center,style:TextStyle(fontSize:20)),
SizedBox(height:20),
Expanded(child:Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("Left Side"),Text("Right Side")
],))
])
)
)));
})
)
);
}
}
Expanded the Text and add a SingleChildScrollView
GridView.count(
crossAxisCount: 2,
childAspectRatio: _aspectRatio,
children: List.generate(myList.length, (index) {
return GridTile(
header: GridTileBar(title:Text(DateTime.now().toString()),backgroundColor: Colors.red,),
child:
SingleChildScrollView(child:Container(color:Colors.yellow,width:double.infinity,height:1200,
child:Card(
child:SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 50.0),
child:Expanded(child:Column(
crossAxisAlignment: CrossAxisAlignment.center ,
mainAxisAlignment: MainAxisAlignment.center,
children:[
//Container(color:Colors.yellow,width:double.infinity,height:600,child: Text(myList[index],textAlign:TextAlign.center,style:TextStyle(fontSize:20)))
Expanded(child:Text(myList[index],textAlign:TextAlign.center,style:TextStyle(fontSize:20)))
,
SizedBox(height:20),
Expanded(child:Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("Left Side"),Text("Right Side")
],))
]))
)
)))));
})
)

Flutter GridView.count is not displaying all items

I'm trying to display the data using GridView.count but it is not displaying all items. here is my code
class CategoriesBody extends StatefulWidget {
const CategoriesBody({Key? key}) : super(key: key);
#override
_CategoriesBodyState createState() => _CategoriesBodyState();
}
class _CategoriesBodyState extends State<CategoriesBody> {
Widget header() {
return Center(
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.2,
width: MediaQuery.of(context).size.width,
child: Container(
color: appThemeColor,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Align(
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
customText(context, "Available", 25.0,
FontWeight.w600, Colors.white),
customText(context, "Categories", 35.0,
FontWeight.w600, Colors.white),
]))))),
);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: objResult == ""
? Column(
children: [
header(),
showCircularLoader(context),
],
)
: objResult == "not connected"
? Column(
children: [
header(),
SizedBox30(),
noInternetConnection(context)
],
)
: apiError == "Server down"
? Column(
children: [
header(),
SizedBox30(),
serverError(context),
],
)
: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
header(),
//list of all categries
SizedBox(
height: MediaQuery.of(context).size.height *
0.97,
child: GridView.count(
crossAxisCount: 2,
scrollDirection: Axis.vertical,
children: List.generate(category.length,
(index) {
return InkWell(
child: customCategoryContainer(
context,
"assets/img/cat2.jpg",
category.length != 0
? category[index].title
: "",
18.0,
MediaQuery.of(context)
.size
.height *
0.18,
MediaQuery.of(context)
.size
.height *
0.18));
}))),
]))));
}
}
api response count is 12, but its displaying 10 items. please help where i'm doing wrong.
The items are probably there but larger than the screen height. And because you have a SingleChildScrollView and it's a scrollable widget, then the Grid is not scrollable, and the Grid and header are taking in total the full height of the screen and not more than that, so the SingleChildScrollView is also not scrollable.
One solution I can think of is to disable the scroll for the SingleChildScrollView widget and force scroll always for the Grid like so:
SingleChildScrollView(
physics: const NeverScrollableScrollPhysisc(),
//...
child: Column(
children: [
//...
SizedBox(
height: MediaQuery.of(context).size.height * 0.97,
child: GridView.count(
physics: const AlwaysScrollableScrollPhysics(),
//...
)
),
]
),
)
This will make the header fixed, and the grid scrollable within the screen height it occupies.
SingleChildScrollView(
physics: const NeverScrollableScrollPhysisc(),
//...
child: Column(
children: [
//...
Expanded(
child: GridView.count(
physics: const AlwaysScrollableScrollPhysics(),
//...
)
),
]
),
)
If this error happens to someone then set the height of SizedBox of GridView.count instead giving it to full screen height, this solve the issue.

Horizontal viewport was given unbounded height - Flutter

I'm a newbie in App development and encountering an error while rendering the Horizontal Card scroll.
howItWorks.dart
class HowItWorksCards extends StatefulWidget {
HowItWorksCards();
#override
_HowItWorksCardsState createState() => _HowItWorksCardsState();
}
class _HowItWorksCardsState extends State<HowItWorksCards> {
int _currentPage = 0;
PageController _pageController = PageController(viewportFraction: 0.8, keepPage: true);
List<Widget> _pages = [
SliderPage(
index: 1,
title: "Title1",
info:"Summary",
image: "assets/images/howItWorks/1.png"),
SliderPage(
index: 1,
title: "Title1",
info:"Summary",
image: "assets/images/howItWorks/1.png"),
SliderPage(
index: 1,
title: "Title1",
info:"Summary",
image: "assets/images/howItWorks/1.png"),
];
_onchanged(int index) {
setState(() {
_currentPage = index;
});
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
flex: 5,
child: PageView.builder( // this throws the exception.
controller: _pageController,
// physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: _pages.length,
onPageChanged: _onchanged,
itemBuilder: (context, int index) {
return _pages[index];
},
),
),
Flexible( // this works absolutely fine when the above Flexible widget is commented.
flex: 4,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(
_pages.length,
(int index) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
height: 5,
width: (index == _currentPage) ? 30 : 10,
margin: EdgeInsets.symmetric(horizontal: 5, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: (index == _currentPage)
? AppTheme.globalTheme.primaryColor
: AppTheme.globalTheme.primaryColor
.withOpacity(0.5)));
},
)),
),
],
);
}
}
slider.dart
class SliderPage extends StatelessWidget {
final String image;
final int index;
final String title;
final String info;
SliderPage(
{#required this.image,
#required this.info,
#required this.title,
#required this.index});
#override
Widget build(BuildContext context) {
return Card(
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(5.0),
height: 175,
child: Image.asset(
image,
fit: BoxFit.fitHeight,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(left: 5),
child: Text(this.title,
style: getFontStyle(
bold: true,
color: Color(0xFF3C3C43),
fontSize: 18,
fontStyle: FontStyles.SFProDisplay),
textAlign: TextAlign.center),
),
],
),
),
Container(
padding:
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5),
child: Text(
this.info,
style: getFontStyle(
color: Color(0xFF3C3C43),
fontSize: 16,
fontStyle: FontStyles.SFProDisplay),
textAlign: TextAlign.center,
),
),
]),
);
}
}
main.dart
void main() => runApp(MaterialApp(home: AmazonOrdersInvoiceOnboarding()));
class AmazonOrdersInvoiceOnboarding extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: GoBackAppBar(
customBackGroundColor: Color(0x1affb500),
title: "",
),
body: ListView(
shrinkWrap: true,
children: [
HowItWorksCards(),
],
),
);
}
}
I'm getting some exceptions.
Horizontal viewport was given unbounded height. - Have already used Flexible. Not sure why I'm still getting this exception.
RenderBox was not laid out: RenderViewport#c29be NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I found a lot of related questions on SO, but to no avail.
This error happen when we use infinite sized widget inside one-another,
here you are using Column inside ListView, both take infinite height, if you wrap Column fixed sized widget it will solve the problem,
And I strongly suggest you to watch this video by flutter
https://www.youtube.com/watch?v=jckqXR5CrPI
on howItWorks.dart
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
flex: 5,
child: Container(
height: 250,
child: PageView.builder(
// this throws the exception.
controller: _pageController,
// physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: _pages.length,
onPageChanged: _onchanged,
itemBuilder: (context, int index) {
return _pages[index];
},
),
),
),
Flexible(
// this works absolutely fine when the above Flexible widget is commented.
flex: 4,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: List<Widget>.generate(
_pages.length,
(int index) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
height: 5,
width: (index == _currentPage) ? 30 : 10,
margin: EdgeInsets.symmetric(horizontal: 5, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.amber)
// (index == _currentPage)
// ? AppTheme.globalTheme.primaryColor
// : AppTheme.globalTheme.primaryColor
// .withOpacity(0.5))
);
},
)),
),
],
);
}