Reputation: 2559
I have a TabBarView() with an amount of different views. I want of them to be a Column with a TextField at top and a ListView.Builder() below, but both widgets should be in the same scrollable area (scrollview). The way I implemented it threw some errors:
@override
Widget build(BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: new TextField(
decoration: new InputDecoration(
hintText: "Type in here!"
),
)
),
new ListView.builder(
itemCount: _posts.length, itemBuilder: _postBuilder)
],
);
}
Error:
I/flutter (23520): The following assertion was thrown during performResize():
I/flutter (23520): Vertical viewport was given unbounded height.
I/flutter (23520): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (23520): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (23520): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (23520): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (23520): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (23520): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (23520): the height of the viewport to the sum of the heights of its children.
I read about stacking the ListView.builder() in an Expanded-Area but it made the textfield kind of "sticky" which is not what I want. :-)
I also came across CustomScrollView but didn't fully understand how to implement it.
Upvotes: 147
Views: 208730
Reputation: 263
Put this inside ListView builder
shrinkWrap: true,
physics: BouncingScrollPhysics()
Upvotes: 0
Reputation: 11
Just Use physics inside listview Builder and then it will be work as scrollable.
ListView.builder(
physics: ScrollPhysics(), // add this
shrinkWrap: true,
itemCount: rentalTypes.length,
itemBuilder: (BuildContext context,index){
String details = rentalTypes[index]['houseDetails'];
String rent = rentalTypes[index]['rent'];
return PostItem(image: AssetImage("assets/images/bedroom.jpg"), description: details, price: rent);
}
)
Upvotes: 1
Reputation: 337
In my case, I added a Container with transparent color and height up to 270 to solve this one.
Column(
children: <Widget>[
ListView(
shrinkWrap: true, // use it
),
Container(
color: Colors.transparent,
height: 270.0,
),
],
)
Upvotes: 1
Reputation: 31
body: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: [
getFiltersOnHomePage(),
SizedBox(
child: StreamBuilder(
stream: FirebaseFirestore.instance.collection('posts').snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (ctx, index) => Container(
margin: EdgeInsets.symmetric(
horizontal: width > webScreenSize ? width * 0.3 : 0,
vertical: width > webScreenSize ? 15 : 0,
),
child: PostCard(
snap: snapshot.data!.docs[index].data(),
),
));
},
),
),
],
),
),[enter image description here][1]***You will be able to scroll through the page by using Expanded Widget
Blockquote Using this you can scroll over the entire page. This page includes a row and a listview builder inside a scrollable column.
Upvotes: 2
Reputation: 1615
return Column(
children: [
Text("Popular Category"),
Expanded(
child: ListView.builder(`enter code here`
shrinkWrap: false,
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("hello"),
],
);
}),
),
],
);
Upvotes: 1
Reputation: 34210
Use SingleChildScrollView
which allows the child widget to scroll
Solution
SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
Two properties used here
shrinkWrap: true
only occupies the space it needs (it will still scroll when there more items).
physics: NeverScrollableScrollPhysics()
Scroll physics that does not allow the user to scroll. Means only Column+SingleChildScrollView Scrolling work.
Upvotes: 74
Reputation: 492
just add
Column(
mainAxisSize: MainAxisSize.max, //Add this line onyour column
children:[
SomeWidget(),
Expanded(child:ListView.builder())
]
)
Upvotes: 12
Reputation: 245
//If you want Listview.builder inside ListView and want to scroll the parent ListView// //whenever the Items in ListView.builder ends or start you can do it like this
body: ListView(
physics: ScrollPhysics(),
children: [
SizedBox(height: 20),
Container( height: 110.0 *5, // *5 to give size to the container //according to items in the ListView.builder. Otherwise will give hasSize Error
child:ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: 5,
itemBuilder: (BuildContext context, int indexChild) {
return InkWell(child:Container(height:100));}))
),]),
Upvotes: 7
Reputation: 566
Here is an efficient solution:
class NestedListExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
const SliverToBoxAdapter(
child: Text('Header'),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, index) {
return ListTile(title:Text('Item $index'));
},
),
),
],
);
}
}
Here is a preview on dartpad.
You can use a SliverToBoxAdapter for the other children as only Slivers can be a direct child of a CustomScrollView.
If all the list items are the same height, then you could use SliverFixedExtentList, which is more efficient because the height of each child isn't calculated on the fly, but you will have to know the exact pixel height. You could also use a SliverPrototypeExtentList, where you provide the first item in the list(the prototype), and all the other children will use the height of the prototype so you don't need to know the exact height in pixels.
Upvotes: 19
Reputation: 231
Use physics: NeverScrollableScrollPhysics() and shrinkWrap: true inside ListView.Builder() and enjoy
Upvotes: 23
Reputation: 1474
In my case with a future i did it like this:
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Hey ho let's go!"),
Flexible(
child: FutureBuilder(
future: getData(),
builder: (BuildContext context,
AsyncSnapshot<List<Sale>> snapshot) {
if (snapshot.connectionState != ConnectionState.done ||
snapshot.hasData == null) {
return CircularProgressIndicator();
} else {
data = snapshot.data;
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return dataItemWidget(size, data[index], context);
},
itemCount: data.length,
);
}
},
),
),
],
),
),
Upvotes: 6
Reputation: 453
Add physics: NeverScrollableScrollPhysics()
inside Listview.builder()
method and the nested Listview
will scroll
Upvotes: 2
Reputation: 31
Just add physics: NeverScrollableScrollPhysics() in ListView.builder() so you can scroll
Upvotes: 3
Reputation: 121
Use Expanded widget to constrain without overflowing those pixels, :)
Column(
children: <Widget>[
Expanded(
child: ListView(),
),
Expanded(
child: ListView(),
),
],
)
Upvotes: 10
Reputation: 3156
Here is the solution:
SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: <Widget>[
Text('Hey'),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount:18,
itemBuilder: (context,index){
return Text('Some text');
})
],
),
),
Upvotes: 309
Reputation: 267554
Reason for the error:
Column
expands to the maximum size in main axis direction (vertical axis), and so does the ListView
Solution
You need to constrain the height of the ListView
, so that it does expand to match Column
, there are several ways of solving this issue, I'm listing a few here:
If you want to allow ListView
to take up all remaining space inside Column
use Flexible
.
Column(
children: <Widget>[
Flexible(
child: ListView(...),
)
],
)
If you want to limit your ListView
to certain height
, you can use SizedBox
.
Column(
children: <Widget>[
SizedBox(
height: 200, // constrain height
child: ListView(),
)
],
)
If your ListView
is small, you may try shrinkWrap
property on it.
Column(
children: <Widget>[
ListView(
shrinkWrap: true, // use it
)
],
)
Upvotes: 35
Reputation: 1711
The best way will be to make the column scrollable by making the column child of SingleChildScrollView and then assigning the same ScrollController to both the SingleChildScrollView and the ListView.builder. This will make the text field and the below ListView as scrollable.
Upvotes: 2
Reputation: 3598
Placing the ListView inside an Expanded
widget should solve your problem:
@override
Widget build(BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: new TextField(
decoration: new InputDecoration(
hintText: "Type in here!"
),
)
),
new Expanded(child: ListView.builder(
itemCount: _posts.length, itemBuilder: _postBuilder))
],
);
}
Upvotes: 160
Reputation: 5605
Column
is not scrollable, which is why the TextField
on top wouldn't scroll but the ListView
on the bottom would.
The best way to solve this in my opinion is to make your TextField
the first item in your ListView
.
So you won't need a column, your parent widget is the ListView
, and its children are the TextField
followed by the remaining items you build with _postBuilder
.
Upvotes: 2