Flutter: Errors when wrapping Layoutbuilder and Text in Column - flutter

I currently have a listview with an alphabet scroller on the side. I'm trying to add a searchbox to the top, but whenever I wrap something in a column, I get errors.
Using the current code, ListView inside Stack is throwing Vertical viewport was given unbounded height.
When I remove the column and Text('TestString'), my code works fine. I have tried adding an Expandable around the ListView.Builder but this also doesn't seem to solve it.
#override
Widget build(BuildContext context) {
height = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
title: Text(widget.title,
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
fontWeight: FontWeight.bold)),
centerTitle: true,
),
body: Column(
children: [
Text('TestString'),
new LayoutBuilder(
builder: (context, constraints) {
return new Stack(children: [
//Causes the current issue
ListView.builder(
itemCount: exampleList.length,
controller: _controller,
itemExtent: _itemsizeheight,
itemBuilder: (context, position) {
return Padding(
padding: const EdgeInsets.only(right: 32.0),
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
exampleList[position],
style: TextStyle(fontSize: 20.0),
),
),
));
},
),
Positioned(
right: _marginRight,
top: _offsetContainer,
child: _getSpeechBubble()),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTapDown: (details) {
_onTapDown(details);
},
child: GestureDetector(
onVerticalDragUpdate: _onVerticalDragUpdate,
onVerticalDragStart: _onVerticalDragStart,
onVerticalDragEnd: (details) {
setState(() {
isPressed = false;
});
},
child: Container(
//height: 20.0 * 26,
color: Colors.transparent,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: []..addAll(
new List.generate(_alphabet.length,
(index) => _getAlphabetItem(index)),
),
),
),
),
),
),
]);
},
),
],
),
);
}
_getSpeechBubble() {
return isPressed
? new SpeechBubble(
nipLocation: NipLocation.RIGHT,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
width: 30,
child: Center(
child: Text(
"${_text ?? "${_alphabet.first}"}",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
),
),
],
),
)
: SizedBox.shrink();
}
ValueGetter? callback(int value) {}
_getAlphabetItem(int index) {
return new Expanded(
child: new Container(
width: 40,
height: 20,
alignment: Alignment.center,
child: new Text(
_alphabet[index],
style: (index == posSelected)
? new TextStyle(fontSize: 16, fontWeight: FontWeight.w700)
: new TextStyle(fontSize: 12, fontWeight: FontWeight.w400),
),
),
);
}

You can wrap your LayoutBuilder() with Expanded() like this and it won't show an error.
return Container(
child: Column(
children: [
Text("Header"),
Expanded(
child: ListView.builder(
itemCount:50,
itemBuilder: (BuildContext context, int index) {
return Text("List Item $index");
},
),
),
Text("Footer"),
],
),
);
You can try the code here

Related

not able to return elements with nested gridview builder - fluttter

my case is that I am retrieving values images and text for challenges (like products ...etc), the challenges should appear one by one vertically first the image appears then the text appears over the image in the centre so I used stack and padding and I was able to retrieve one challenge information only, now I want to retrieve all challenges vertically using gridview builder, so I have did this :
Widget build(BuildContext context) {
return GridView.builder(
scrollDirection: Axis.vertical,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: _challenges.length),
itemBuilder: (_, index) {
return InkWell(
onTap: () {},
child: Stack(
children: [
Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image(
image:
NetworkImage(_challenges[index]["image-path"][0]),
fit: BoxFit.cover,
height: 150,
width: 350,
opacity: AlwaysStoppedAnimation(.4),
),
),
),
),
Padding(
padding: const EdgeInsets.all(60.0),
child: Center(
child: Text(
"${_challenges[index]["name"]}\n${_challenges[index]["date"]}",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
),
],
),
);
});
every time i hot reload the app i get this error:
'package:flutter/src/rendering/sliver_grid.dart': Failed assertion: line 319 pos 15: 'crossAxisCount != null && crossAxisCount > 0': is not true.
and in just in case this is how i retrieved the data from Firestore:
List _challenges = [];
fetchChallengeData() async {
var _fireStoreInstance = FirebaseFirestore.instance;
QuerySnapshot qn = await _fireStoreInstance.collection("challenges").get();
setState(() {
for (int i = 0; i < qn.docs.length; i++) {
_challenges.add({
"image-path": qn.docs[i]["image-path"],
"name": qn.docs[i]["name"],
"date": qn.docs[i]["date"],
});
}
});
}
#override
void initState() {
fetchChallengeData();
super.initState();
}
the home screen where i use to display the element looks like:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Text(
"أتحداك",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: SingleChildScrollView(
child: Column(
children: [
AdsBanner(),
SizedBox(
height: 50,
),
Directionality(
textDirection: TextDirection.rtl,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
"التحديات",
style: TextStyle(fontSize: 20),
),
Text(
" (إضغط على التحدي للإشتراك به)",
style: TextStyle(fontSize: 15),
)
],
),
),
),
ChallengeCard(),
],
),
),
endDrawer: NavigationDrawer());
so basically the parent is a column and the parent of the column is singleChildScrollView,
any help I would be grateful, Thanks.
We are getting data from future fetchChallengeData, So it will be null initially, Try returning another widget on null or empty cases
Widget build(BuildContext context) {
return _challenges!=null && _challenges.isNotEmpty? GridView.builder(...): SizedBox.shrink();
Though _challenges.isNotEmpty enough while we've List _challenges = [];
I think we are seeking somthing like this
Widget myGridView() {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, //number of items on single Row
),
itemCount: _challenges.length, // number of item will render
itemBuilder: (context, index) => Text("Your item Builder"),
);
}
Widget placement
body: Column(
children: [
AdsBanner(),
SizedBox(
height: 50,
),
Directionality(
textDirection: TextDirection.rtl,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
"التحديات",
style: TextStyle(fontSize: 20),
),
Text(
" (إضغط على التحدي للإشتراك به)",
style: TextStyle(fontSize: 15),
)
],
),
),
),
Expanded(child: ChallengeCard()),
],
),

Why can't I build the list?

I tried to build a list by taking the data I pulled from the database. But I do not see anything in any way, I get a white screen. I think the data I pulled is overlapping and preventing building lists but I couldn't find where the error is. What I'm trying to do is divide the Card by Row with 2 and write the data I pulled from the database on the left side of the Card. Write other data on the right.
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _db.getEventsByOrder(widget.index),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(child: Text("Loading.....")),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Container(
padding: const EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 16.0),
child: Card(
elevation: 25,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Row(
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Text(
'${snapshot.data[index].title}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 28, fontFamily: 'Arvo'),
)),
Text(
"${snapshot.data[index].date} - ${snapshot.data[index].startTime == "null" ? " Tüm gün" : "${snapshot.data[index].startTime} - ${snapshot.data[index].finishTime}"}",
style: new TextStyle(
fontSize: 15, fontFamily: 'Arvo'),
),
Expanded(
child: Text(snapshot.data[index].desc,
maxLines: 2,
overflow: TextOverflow.ellipsis),
),
]),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: DropDown(Event(
id: snapshot.data[index].id,
title: snapshot.data[index].title,
date: snapshot.data[index].date,
startTime:
snapshot.data[index].startTime,
finishTime:
snapshot.data[index].finishTime,
desc: snapshot.data[index].desc,
isActive:
snapshot.data[index].isActive,
choice:
snapshot.data[index].choice))),
Container(
padding: EdgeInsets.only(top: 8.0),
height: 100,
width: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.blue),
child: Text(
"${DateTime.parse(snapshot.data[index].date).difference(DateTime.now()).inDays}\nKalan Gün",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25),
),
),
],
),
],
),
),
),
);
});
}
}),
);
}
You need to adjust the dimensions only.
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _db.getEventsByOrder(widget.index),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(child: Text("Loading.....")),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Container(
padding: const EdgeInsets.fromLTRB(8.0, 16.0, 8.0, 16.0),
child: Card(
elevation: 25,
child: Container(
height: MediaQuery.of(context).size.height/4,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width / 2 - 16,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
'${snapshot.data[index].title}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 28),
),
Text(
"${snapshot.data[index].date} - ${snapshot.data[index].startTime == "null" ? " Tüm gün" : "${snapshot.data[index].startTime} - ${snapshot.data[index].finishTime}"}",
style: TextStyle(fontSize: 15),
),
Text(
snapshot.data[index].desc,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
Container(
width: MediaQuery.of(context).size.width / 2 - 32,
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width / 4 - 8,
child: DropDown(Event(
id: snapshot.data[index].id,
title: snapshot.data[index].title,
date: snapshot.data[index].date,
startTime: snapshot.data[index].startTime,
finishTime: snapshot.data[index].finishTime,
desc: snapshot.data[index].desc,
isActive: snapshot.data[index].isActive,
choice: snapshot.data[index].choice)),
),
],
),
),
),
);
});
}
}),
);
}
If there was even an overlapping problem, should be an error. Provide the debug info and try to move DropDown out of container to column
You could also close ROW in a CONTAINER

Flutter: How to merge two StreamBuilder and show the output in a card

I'm kinda stuck with what I'm trying to do. I'm trying to merge my two Stream Builder to show the output as one in a card. In my first StreamBuilder thats where I'm getting some infos of the user like the info that he posted, what they need like that. And in my 2nd StreamBuilder thats where I get his/her name, contacts like that. Is it possible to merge it as one? so I'll get the data as one also.
This is how I use my StreamBuilders.
1st stream:
StreamBuilder<QuerySnapshot>(
stream: db.collection('HELP REQUEST').where('Type_OfDisaster', isEqualTo: '[Drought]').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: snapshot.data.documents
.map((doc) => buildItem(doc))
.toList()
);
} else {
return Container(
child: Center(
child: CircularProgressIndicator()
)
);
}
}
);
2nd Stream:
StreamBuilder<QuerySnapshot>(
stream: db.collection('USERS').where('User_ID', isEqualTo: widget.Uid).snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: snapshot.data.documents
.map((doc) => buildItem(doc))
.toList()
);
} else {
return Container(
child: Center(
child: CircularProgressIndicator()
)
);
}
}
);
Here is where I output the data I get in the stream builder:
Container buildItem(DocumentSnapshot doc) {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
return Container(
child: Card(
elevation: 5,
child: Padding(
padding: const EdgeInsets.only(top: 20, left: 20, right: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(
radius: 30,
backgroundColor: Colors.black,
),
SizedBox(
width: 10,
),
Text('Name: '),
Text(
'${doc.data['Name_ofUser']}',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w500),
)
],
),
],
),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 20,
),
Row(
children: <Widget>[
Text('Date:'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${doc.data['Help_DatePosted']}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w500),
),
),
],
),
Row(
children: <Widget>[
Text('Location:'),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${doc.data['Help_Location']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text('Description:'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${doc.data['Help_Description']}',
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Container(
height: _height * 0.05,
width: _width * 0.20,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(20.0))),
color: Color(0xFF121A21),
onPressed: () {
_viewingRequest(doc.data);
},
child: Text(
'View',
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.w800),
),
),
),
)
],
),
],
),
),
),
);
}
Is it possible to do it? Please help me.
You can listen to the snapshots without using a StreamBuilder directly, like this:
List<HelpRequestsPlusUsers> helpRequestsPlusUsers = [];
List<User> allUsers = [];
List<HelpRequest> helpRequests = [];
#override
void initState() {
db.collection('USERS').where('User_ID', isEqualTo: widget.Uid).snapshots().listen((snapshot){
allusers = snapshot.data.documents;
mergeUsersWithHelpRequests();
});
db.collection('HELP REQUEST').where('Type_OfDisaster', isEqualTo: '[Drought]').snapshots().listen((snapshot){
helpRequests = snapshot.data.documents;
mergeUsersWithHelpRequests();
});
super.initState();
}
void mergeUsersWithHelpRequests(){
// Run the code to merge your allUsers and helpRequests data into a helpRequestsPlusUsers List
}
Widget
Widget _buildHelpRequestsPlusUsersWidget (){
if (helpRequestsPlusUsers.isNotEmpty) {
return ListView.builder(
itemBuilder: (context, index){
return buildItem(helpRequestsPlusUsers[index]);
}
);
} else {
return Container(
child: Center(
child: CircularProgressIndicator()
)
);
}
}

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(...