Reputation: 547
I want to be able to have a ListView within a Card and the Card's height will be decided by the ListView's height (later on I will limit the list to x items so that it won't take the entire space if there are many items.
This is an example I wrote that illustrates the "challenge", see the comment below the ListView.builder():
import 'package:flutter/material.dart';
void main() => runApp(new MyExample());
class MyExample extends StatelessWidget {
final List<int> _data = [1, 2, 3, 4, 5, 6, 7];
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: new AppBar(title: new Text('Example')),
body: new Container(
child: new Column(
children: <Widget>[
new Card(
child: new SizedBox(
height: 100.0,
width: 440.0,
child: new Center(
child: new Text('First card'),
),
),
),
new Card(
child: new SizedBox(
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) =>
new MyExampleListItemWidget(_data[index]),
itemCount: _data.length,
),
/// This is the one I want to be dynamic. The more items there are the more space it takes and the less space section 3 gets.
height: 100.0,
),
),
new Flexible(
child: new Center(
child: new Text('The third section'),
),
),
],
),
),
),
);
}
}
class MyExampleListItemWidget extends StatelessWidget {
final int _index;
MyExampleListItemWidget(this._index) : super();
@override
Widget build(BuildContext context) {
return new Padding(
padding: new EdgeInsets.all(5.0),
child: new Text('Text ' + _index.toString()));
}
}
Upvotes: 0
Views: 6493
Reputation: 6646
Okay, late answer, but incase people are still looking for some kind of solution. There are probably many ways to do this, but building off of the OPs sample/requirements, the key is to combo it with the ListView's shrinkWrap
property. A simplified example:
Card(
child: SizedBox(
height: _boxHeight,
child: ListView.builder(
shrinkWrap: _shrinkWrap,
controller: _controller,
itemCount: _myList.length,
itemBuilder: (context, index) {
return _myList[index];
}),
)
),
In initState()
, you will initiate the minimum height of this SizedBox
based on some conditions like the minimum amount of items in the list:
if (_myList.length <= listMinSize) {
_boxHeight = minBoxHeight;
_shrinkWrap = false;
}
Then whenever the list grows, you will check the conditions to either enable shrinkWrap
or to set the maximum height of the box.
setState(() {
listChanged();
if (_myList.length > listMaxSize) { // lock box height, disable shrinkWrap
_boxHeight = maxBoxHeight;
_shrinkWrap = false;
} else if (_myList.length > listMinSize) { // unconstrain box height, enable shrinkWrap
_boxHeight = null;
_shrinkWrap = true;
} // can also check if it ever returns to listMinSize
});
In short, this will let your Card/SizedBox
start off at minBoxHeight
, grow with the ListView
until it reaches listMaxSize
, locking in at maxBoxHeight
, at which point it'll have a scrolling behavior.
Now, if you wanted to make sure that the min/max boxHeights are nicely aligned with the list items, then that's a whole other issue, where you'll need to calculate the list item widget sizes and their list offsets.
Upvotes: 1