RenderBox was not laid out, Flutter Listview Builder not Displaying - flutter

I'm New to this Framework, And I'm Unable to Display the ListViewBuilder Items. I'm Getting this error in Console
════════ Exception caught by rendering library ═════════════════════════════════
RenderBox was not laid out: RenderRepaintBoundary#f28ee relayoutBoundary=up14 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1785 pos 12: 'hasSize'
class _ViewCartState extends State<ViewCart> {
List<dynamic> cartData;
#override
void initState() {
super.initState();
APIService apiService = new APIService();
apiService.apiCall().then((value) async {
setState(() {
cartData = value.data.result.cartData;
print(cartData);
});
});
}
#override
Widget build(BuildContext context) {
loadData();
var veg;
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(
color: kHintColor, //change your color here
),
title: Text("Cart Page", style: Theme.of(context).textTheme.bodyText1),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
// width: 500, //if this Height I'm Not giving Then List not Displaying.
padding: EdgeInsets.all(20.0),
color: Theme.of(context).cardColor,
child: Text("Your Cart Items",
style: Theme.of(context)
.textTheme
.headline6
.copyWith(
color: Color(0xff616161),
letterSpacing: 0.67)),
),
Divider(
color: Theme.of(context).cardColor,
thickness: 1.0,
),
Padding(
padding: const EdgeInsets.all(10),
child: ListView.builder(
itemCount: cartData.length,
itemBuilder: (context, index) => Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cartItemListTile(context, cartData, index),
],
),
),
),
),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
BottomBar(
text: "go to next page"),
],
),
),
],
),
);
}
This is my ListView builder Return Function
ListTile cartItemListTile(
BuildContext context, List<dynamic> cartData, int index) {
int qty;
return ListTile(
title: Padding(
padding: EdgeInsets.only(top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Image.network(
cartData[index].itemimage.image,
height: 40,
width: 40,
),
]),
),
);
}
}
Please help me with that. I cant Set the Container Height Because I have lots of Fields out of that List Also.

In the Listview.builder
Add these 2 lines ..
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,

Related

Flutter - ListView nested in columns gives error "hasSize"

I have a ListView.builder() nested inside multiple columns, I get the following error and the widget doesn't build at all due to this:
════════ Exception caught by rendering library
═════════════════════════════════ RenderBox was not laid out:
RenderShrinkWrappingViewport#813d4 relayoutBoundary=up40 NEEDS-PAINT
NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
package:flutter/…/rendering/box.dart:1 Failed assertion: line 1982 pos
12: 'hasSize'
The relevant error-causing widget was ListView
lib\…\Widgets\todolistmodule_briefcard.dart:81
Below is the code:
class TodolistModuleBriefCard extends StatelessWidget {
//const NotesBriefModule({ Key? key }) : super(key: key);
TodolistModule todolistModule;
TodolistModuleBriefCard({required this.todolistModule});
#override
Widget build(BuildContext context) {
return buildCard();
}
Widget buildCard() => Padding(
padding: EdgeInsets.symmetric(vertical: 5),
child: Container(
child: Card(
color: Color.fromARGB(255, 240, 240, 240),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
child: buildContent(),
),
),
);
Widget buildContent() => Column(
children: [
buildName(),
Divider(
height: 1,
),
buildTodoList()
],
);
Widget buildName() => Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
child: Text(
todolistModule.name,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontFamily: AppConfig.primaryFontFamily,
fontSize: 17,
color: Colors.grey.shade700,
fontWeight: FontWeight.w500,
),
),
);
Widget buildTodoList() => Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
buildTodoListSubList(
subList: todolistModule.todo, subListTitle: "To Do"),
buildTodoListSubList(
subList: todolistModule.completed, subListTitle: "Complete")
],
),
);
Widget buildTodoListSubList(
{required List<String> subList, required String subListTitle}) =>
Column(
children: [
buildTodoListSubListTitle(title: subListTitle),
buildTodoListSubListItems(subList: subList),
],
);
Widget buildTodoListSubListTitle({required String title}) => Text(
title,
style: TextStyle(fontFamily: AppConfig.primaryFontFamily),
);
Widget buildTodoListSubListItems({required List<String> subList}) =>
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: subList.length,
itemBuilder: ((context, index) {
return buildTodoListSubListItem(item: subList[index]);
}),
);
Widget buildTodoListSubListItem({required String item}) => Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text(item,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 3,
style: TextStyle(
fontFamily: AppConfig.primaryFontFamily, fontSize: 13)),
),
);
}
Could someone please help me solve this problem?
just add Expanded
Widget buildTodoList() => Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: buildTodoListSubList(
subList: todolistModule.todo, subListTitle: "To Do"),
),
Expanded(
child: buildTodoListSubList(
subList: todolistModule.completed, subListTitle: "Complete"),
)
],
),
);
But you need read more about the layout principle
there is two solution:
you can surround your ListView with a container with a certain height like a height of your screen from media query for example:
Column(children: [
Container(
width: double.infinity,
height: 400,
child: ListView.builder(
itemBuilder: (context, index) {
return Container(
width: 200,
height: 890,
color: Colors.red,
child: Text('Hello'),
);
},
itemCount: 1,
),
)
]),
the second solution but I think it will stop the scrollable but try it is to set shrinkWrap property in listView to true like this:
Column(children: [
ListView.builder(
shrinkWrap: true, // this is shrinkWrap property!!!
itemBuilder: (context, index) {
return Container(
width: 200,
height: 400,
color: Colors.red,
child: Text('Hello'),
);
},
itemCount: 1,
)
]),

Cannot put PageView into Column in Flutter

I want to put a small PageView into a Column, but I got error RenderBox was not laid out: RenderRepaintBoundary#db5f8 relayoutBoundary=up14 NEEDS-PAINT. The PageView will hold inconsistent data so I cannot set the height for it. Can anyone help me? This is my code:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
bottomNavigationBar: BottomAppBar(
child: Container(
height: 70,
color: Colors.white,
),
),
body: FutureBuilder(
future: Data.getProductDetails(id: widget.product.id),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator(color: Colors.grey));
} else {
List iList = [];
iList.add(widget.product.mainImg);
for (ProductImages i in snapshot.data.imgList) {
iList.add(i.image);
}
return CustomScrollView(
slivers: [
SliverAppBar(...),
SliverToBoxAdapter(
child: SingleChildScrollView(
padding: EdgeInsets.all(15),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(...),
Row(...),
SizedBox(height: 10),
brandField(snapshot),
SizedBox(height: 5),
categoryField(snapshot),
SizedBox(height: 5),
tagsField(snapshot),
SizedBox(height: 20),
pageIndicator(),
Expanded(
child: PageView(
children: [
Container(height: 400, color: Colors.red),
Container(height: 600, color: Colors.blue),
],
),
)
],
),
),
),
],
);
}
},
),
);
}
You get this error because PageView and other widgets like ListView require size constraints from its parents and Column do not provide constraints to its children. So to solve the issue you can wrap you PageView inside Flexible or Expanded like so:
Column(
children:[
Expanded(child:PageView(),),
]
)
For better understanding of constrains in flutter, read: Understanding Constrains: Flutter.dev

Exception caught by widgets library A build function returned null

I am fairly new to flutter development. I am trying to have static header and grid card items that scroll underneath the static header, but I end up getting the error. I have tried to research no success. What am i doing wrong?
Exception caught by widgets library A build function returned null.
The relevant error-causing widget was: GridDashboard
and
A RenderFlex overflowed by 99515 pixels on the bottom. The relevant
error-causing widget was: Column
my griddashboard class
class GridDashboard extends StatelessWidget {
var services = [
"Home",
"Settings",
"Supervisor",
"Logout",
"Forms",
"Messages",
"bluetooth",
"Check for updates",
"Update"
];
var images = [
"images/calendar.png",
"images/festival.png",
"images/food.png",
"images/image.png",
"images/logout.png",
"images/setting.png",
"images/note.png",
"images/todo.png",
"images/map.png",
];
#override
Widget build(BuildContext context) {
// return Padding(
// padding: const EdgeInsets.all(8.0),
// child:
GridView.builder(
itemCount: services.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width/(MediaQuery.of(context).size.height/1.4)
),
itemBuilder: (BuildContext context, int index){
return Card(
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Image.asset(images[index], height: 50.0, width: 50.0,),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(services[index], style: TextStyle(fontSize: 16.0, height: 1.2),textAlign: TextAlign.center ,),
)
],
),
);
},
// ),
);
}
}
my home class
class Home extends StatefulWidget {
#override
HomeState createState() => new HomeState();
}
class HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xff392850),
body: Column(
children: <Widget>[
SizedBox(
height: 110,
),
Padding(
padding: EdgeInsets.only(left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Full Names",
style: GoogleFonts.openSans(
textStyle: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold)),
),
SizedBox(
height: 4,
),
Text(
"Home",
style: GoogleFonts.openSans(
textStyle: TextStyle(
color: Color(0xffa29aac),
fontSize: 14,
fontWeight: FontWeight.w600)),
),
],
),
IconButton(
alignment: Alignment.topRight,
icon: Image.asset(
"assets/notification.png",
width: 24,
),onPressed: ()=>{
},
),
],
),
),
SizedBox(
height: 40,
),
GridDashboard()
],
),
);
}
}
You removed the return keyword from your build function, probably by accident.
GridView.builder(
needs to be
return GridView.builder(
Otherwise your build function returns nothing and you get the errors you are getting now.
as it says your build function was called on null which means you forgot write return out;
your problem is in griddashboard class where you wrote this
Widget build(BuildContext context) {
// return Padding(
// padding: const EdgeInsets.all(8.0),
// child:
GridView.builder(
itemCount: services.length
every time you don't write return in a function it shows that error , not only the build function , so you can handle it by writing return like this
Widget build(BuildContext context) {
return GridView.builder(
itemCount: services.length

Handle listview item height?

So i have this script which is build a listview
class NewProductsLists extends StatelessWidget {
final List<NewProducts> newlist;
NewProductsLists({Key key, this.newlist}) : super(key: key);
final formatCurrency =
new NumberFormat.simpleCurrency(locale: "id", decimalDigits: 2);
#override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
itemCount: newlist.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
print("Product detail");
},
child: Card(
child: Container(
width: MediaQuery.of(context).size.width * 0.50,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.network(
Configuration.url +
"assets/app_assets/" +
newlist[index].productImage,
width: 90,
height: 90,
filterQuality: FilterQuality.low),
ListTile(
title: Center(
child: Text(
newlist[index].productName,
style: TextStyle(fontSize: 18),
)),
subtitle: Center(
child: Text(
formatCurrency.format(
int.parse(newlist[index].productPrice)),
style: TextStyle(color: Colors.red, fontSize: 15),
)),
),
],
)),
),
);
}));
}
}
and the result looks like this
[
As you can see the card is expanding so hard. I know it is because the Expanded widget. Is it possible to make the card wrap_content ?
For horizontal list view needs fixed height if its not going to be vertical scrollable view you can use Expanded widget with varying flex to get it working.
Working build widget by using expanded widget.
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
centerTitle: false,
title: const Text('November'),
),
body: new Container(
child: Column(
children: <Widget>[
new Expanded(flex: 1,child: new Container(color: Colors.grey[300],),),
Expanded(flex: 2,
child: ListView.builder(
itemCount: 10,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
print("Product detail");
},
child: Card(
child: Container(
width: MediaQuery.of(context).size.width * 0.50,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.network(
'https://homepages.cae.wisc.edu/~ece533/images/watch.png',
width: 90,
height: 90,
filterQuality: FilterQuality.low),
ListTile(
title: Center(
child: Text(
'item Name ${index}',
style: TextStyle(fontSize: 18),
)),
subtitle: Center(
child: Text(
'\$10',
style: TextStyle(
color: Colors.red, fontSize: 15),
)),
),
],
)),
),
);
}),
),
new Expanded(flex: 3,child: new Container(color: Colors.amber[100],),),
],
)));
}
Result screen
Let me know if it suits your requirement.

Flutter dynamic height of ListView

I am developing a Flutter application and I want to dynamically adjust the height of the ListView.
I want the list to have a maximum height of 200. If the height is more than that, user will have to scroll to reach the bottom. If height is below 200, it will take only as much space as needed.
Preview of application: Screenshot. As you can see Restaurants nearby is pushed to the very bottom of the page. I want the ListView to only take height of 200 or less so that the content below isn't pushed to the bottom.
Here is my current code:
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Enter restaurant manually'),
onPressed: () {
print('Button pressed');
},
),
],
),
Flexible(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
You are using Flexible widget, that's why your ListView expands. You have to change Flexible to ConstrainedBox and add shrinkWrap: true to your ListView.
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200, minHeight: 56.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
More info here: https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html
You can use LimitedBox
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(...),
Divider(),
Row(...),
LimitedBox(
maxHeight: 200.0,
child: ListView.builder(...),
),
Text(...),
],
),
Recommended solution in case when the incoming constraints are unbounded
Consider wrapping the ListView into this
LimitedBox(
maxHeight: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: _itemsCount,
),
),
]
)
),
Note that:
shrinkWrap of ListView is set to true
mainAxisSize of Column is set to MainAxisSize.min
maxHeight of LimitedBox is set to 200
A complete snippet:
import 'package:flutter/material.dart';
class DebugWidget extends StatefulWidget {
#override
_DebugWidgetState createState() => _DebugWidgetState();
}
class _DebugWidgetState extends State<DebugWidget> {
int _itemsCount = 1;
#override
Widget build(BuildContext context) {
Widget child = Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Enter restaurant manually'),
onPressed: () {
print('Button pressed');
},
),
RaisedButton(
child: Text('+1'),
onPressed: () {
setState(() {
_itemsCount += 1;
});
},
),
RaisedButton(
child: Text('-1'),
onPressed: () {
setState(() {
_itemsCount -= 1;
});
},
),
],
),
LimitedBox(
maxHeight: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: _itemsCount,
),
),
]
)
),
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
],
),
);
return Scaffold(
body: child,
);
}
}
I found a solution to this problem. you should wrap your ListView with LimittedBox or ConstraintBox and give them maxHeight and set shrinkWrap property of ListView to true. the solution would be something like this.
LimitedBox(
maxHeight: 200,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
I see that this question has never been answered only with giving a fixed height, so here is what works for me.
For some reason if you set the shrinkwrap to true it doesn't look like it is working but it does, the problem is in the padding settings of the ListView, set the padding to edgeinstets.zero. That fixes it for me.
Wrap inside a Flexible
ShrinkWrap true
Padding, zero
and if needed the column to MainAxisSize.min.
Hope it helps some people.
Example of my code:
Flexible(
child: Container(
decoration: BStyles.cardDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'PRODUCTION TASKS',
),
const SizedBox(
height: textVerticalSpacing,
),
Flexible(
child: ListView.builder(
itemCount: recentTasks.length,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return TaskCard(
task: recentTasks[index],
widthInfo: MediaQuery.of(context).size.width * 0.6,
);
},
),
),
const SizedBox(
height: itemSpacing,
),
Align(
alignment: Alignment.centerRight,
child: InkWell(
onTap: () { },
child: const Text(
'View more',
),
),
),
const SizedBox(
height: textVerticalSpacing,
),
],
),
),
),
),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200.0),
child: [your child here],
)
This make your child's height not bigger than 200.0
You can always size the ListView container as % of the viewport (assuming of course that the other widgets also are sized in the same manner):
return Container(
height: MediaQuery.of(context).size.height * 0.75,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Card(...