Reputation: 9149
I'm trying to construct a simple login page for my Flutter app. I've successfully built the TextFields and log in/Sign in buttons. I want to add a horizontal ListView. When I run the code my elements disappear, if I do it without the ListView, it's fine again. How can I do this correctly?
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Login / Signup"),
),
body: new Container(
child: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField(
decoration: new InputDecoration(
hintText: "E M A I L A D D R E S S"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(obscureText: true,
decoration: new InputDecoration(
hintText: "P A S S W O R D"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(decoration: new InputDecoration(
hintText: "U S E R N A M E"
),),
new RaisedButton(onPressed: null,
child: new Text("SIGNUP"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new RaisedButton(onPressed: null,
child: new Text("LOGIN"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new ListView(scrollDirection: Axis.horizontal,
children: <Widget>[
new RaisedButton(onPressed: null,
child: new Text("Facebook"),),
new Padding(padding: new EdgeInsets.all(5.00)),
new RaisedButton(onPressed: null,
child: new Text("Google"),)
],)
],
),
),
margin: new EdgeInsets.all(15.00),
),
),
);
Upvotes: 430
Views: 302094
Reputation: 11
Column(
children: <Widget>[
Expanded( //
child: ListView(...),
)
],
)
Upvotes: 0
Reputation: 41
You can use SizedBox and give it a height or you can use Expanded
Upvotes: 0
Reputation: 1
import 'package:flutter/material.dart';
/// Enum representing different types of ListViews.
enum CustomListViewType {
basicListView,
horizontalListView,
builderListView,
separatedListView,
}
/// A highly customizable and reusable ListView widget.
/// Supports basic, horizontal, builder, and separated ListView types.
class CustomListView extends StatelessWidget {
final CustomListViewType type;
final List<Widget>? items; // For basic and horizontal ListViews
final IndexedWidgetBuilder? itemBuilder; // For builder and separated ListViews
final IndexedWidgetBuilder? separatorBuilder; // For separated ListViews
final int? itemCount; // Number of items
final EdgeInsetsGeometry? padding; // Padding for the ListView
final Axis scrollDirection; // Vertical or horizontal scrolling
final ScrollPhysics? physics; // Scrolling behavior
final bool shrinkWrap; // Whether to shrink-wrap content
final bool reverse; // Whether to reverse the scroll direction
const CustomListView({
required this.type,
this.items,
this.itemBuilder,
this.separatorBuilder,
this.itemCount,
this.padding,
this.scrollDirection = Axis.vertical,
this.physics,
this.shrinkWrap = false,
this.reverse = false,
super.key,
});
@override
Widget build(BuildContext context) {
switch (type) {
case CustomListViewType.basicListView:
return _buildBasicListView();
case CustomListViewType.horizontalListView:
return _buildHorizontalListView();
case CustomListViewType.builderListView:
return _buildBuilderListView();
case CustomListViewType.separatedListView:
return _buildSeparatedListView();
}
}
/// Builds a basic ListView with static children.
Widget _buildBasicListView() {
return ListView(
padding: _getPadding(),
scrollDirection: scrollDirection,
physics: physics,
shrinkWrap: shrinkWrap,
reverse: reverse,
children: items ?? [],
);
}
/// Builds a horizontal ListView with static children.
Widget _buildHorizontalListView() {
return ListView(
padding: _getPadding(),
scrollDirection: Axis.horizontal,
physics: physics,
shrinkWrap: shrinkWrap,
reverse: reverse,
children: items ?? [],
);
}
/// Builds a dynamic ListView using an item builder.
Widget _buildBuilderListView() {
return ListView.builder(
padding: _getPadding(),
scrollDirection: scrollDirection,
physics: physics,
shrinkWrap: shrinkWrap,
reverse: reverse,
itemCount: itemCount ?? 0,
itemBuilder: itemBuilder ?? (_, __) => const SizedBox(),
);
}
/// Builds a ListView with separators between items.
Widget _buildSeparatedListView() {
return ListView.separated(
padding: _getPadding(),
scrollDirection: scrollDirection,
physics: physics,
shrinkWrap: shrinkWrap,
reverse: reverse,
itemCount: itemCount ?? 0,
itemBuilder: itemBuilder ?? (_, __) => const SizedBox(),
separatorBuilder: separatorBuilder ?? (_, __) => const Divider(),
);
}
/// Provides the padding for the ListView, falling back to a default value if none is provided.
EdgeInsetsGeometry _getPadding() {
return padding ?? const EdgeInsets.all(8.0);
}
}
class ListViewExamples extends StatelessWidget {
const ListViewExamples({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Custom ListView Examples')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Basic ListView',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
Expanded(
child: CustomListView(
type: CustomListViewType.basicListView,
items: List.generate(
10,
(index) => ListTile(title: Text('Basic Item $index')),
),
),
),
const SizedBox(height: 20),
const Text(
'Horizontal ListView',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
SizedBox(
height: 100,
child: CustomListView(
type: CustomListViewType.horizontalListView,
items: List.generate(
10,
(index) => Container(
width: 100,
margin: const EdgeInsets.symmetric(horizontal: 8),
color: Colors.blue,
child: Center(
child: Text('Item $index',
style: const TextStyle(color: Colors.white)),
),
),
),
),
),
const SizedBox(height: 20),
const Text(
'Builder ListView',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
Expanded(
child: CustomListView(
type: CustomListViewType.builderListView,
itemCount: 15,
itemBuilder: (context, index) =>
ListTile(title: Text('Builder Item $index')),
),
),
const SizedBox(height: 20),
const Text(
'Separated ListView',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
Expanded(
child: CustomListView(
type: CustomListViewType.separatedListView,
itemCount: 10,
itemBuilder: (context, index) =>
ListTile(title: Text('Separated Item $index')),
separatorBuilder: (context, index) => const Divider(),
),
),
],
),
),
);
}
}
Upvotes: 0
Reputation: 477
If you have a Nested Column or Have a ListView inside a column and you dont want to scroll your first column items and want to minimize the size of your column and dont wanna use Expanded then my comment is for you.
What you should do is use Flex
and Flexible
.
Example with Nested column:
Use Flex instead of first Column
Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
widgets_that_you_dont_wants_to_scroll(...),
widgets_that_you_dont_wants_to_scroll(...),
Flexible(
child: SingleChildScrollView(
child: Column(
children: [
...
]
),
),
),
]
),
Example for ListView in Column:
use Flex instead of first column
Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
widgets_that_you_dont_wants_to_scroll(...),
widgets_that_you_dont_wants_to_scroll(...),
Flexible(
child: ListView.builder(
itemCount: 4,
shrinkWrap: true, // Must add
itemBuilder: (context, index) {
return ...
},
),
),
]
),
Upvotes: 1
Reputation: 467
Don't forget to rebuild/restart the app as the hot reload did not reflect or apply when I added an Expanded
around my ListView
Upvotes: 0
Reputation: 595
Instead, I think you need to use an expanded widget.
Column (
children: <Widget>[
new TextField(
decoration: new InputDecoration(
labelText: "Search something"
),
Expanded(
ListView(),
),
]
)
Upvotes: 3
Reputation: 6961
You can check console output. It prints error:
The following assertion was thrown during performResize(): The horizontal viewport was given unbounded height. Viewports expand in the cross axis to fill their container and constrain their children to match their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of vertical space in which to expand.
You need to add a height constraint to your horizontal list. E.g. wrap in SizedBox with height:
SizedBox(
height: 44.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
RaisedButton(
onPressed: null,
child: Text("Facebook"),
),
Padding(padding: EdgeInsets.all(5.00)),
RaisedButton(
onPressed: null,
child: Text("Google"),
)
],
),
)
Upvotes: 160
Reputation: 81
You can wrap your list Flexible
I hope this help you!
Flexible(
child: ListView(
shrinkWrap: true,
primary: true,
scrollDirection: Axis.horizontal,
children: <Widget> [
Wrap(
spacing: 12,
runSpacing: 12,
children: List<Widget>.generate(5, (index) {
return MyChip(
onChange: (p0) {},
);
}),
)
]),
)
Upvotes: 5
Reputation: 268314
Column
expands to the maximum size in main axis direction (vertical axis), and so does the ListView
.
So, you need to constrain the height of the ListView
. There are many ways of doing it, you can choose that best suits your need.
If you want to allow ListView
to take up all remaining space inside Column
, use Expanded
.
Column(
children: <Widget>[
Expanded( // <-- Use Expanded
child: ListView(...),
)
],
)
If you want to limit your ListView
to a certain height
, 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, // Set this
)
],
)
If you want to make ListView
to as small as it can be, use Flexible
with ListView.shrinkWrap
:
Column(
children: <Widget>[
Flexible( // <-- Use Flexible
child: ListView(
shrinkWrap: true, // and set this
),
)
],
)
Upvotes: 429
Reputation: 25
In my case, I was using
and I wanted to scroll last scroll view with the whole column for this add
physics: NeverScrollableScrollPhysics(),
this line in your listview.
Upvotes: 1
Reputation: 34270
Expanded Widget increases its size as much as it can with the space available Since ListView essentially has an infinite height it will cause an error.
Column(
children: <Widget>[
Flexible(
child: ListView(...),
)
],
)
Here we should use the Flexible
widget as it will only take the space it required as Expanded take full screen even if there are not enough widgets to render on full screen.
Upvotes: 48
Reputation: 6009
I've got this problem too. My solution is use Expanded
widget to expand remain space.
Column(
children: <Widget>[
Expanded(
child: horizontalList,
)
],
);
Upvotes: 600
Reputation: 2129
[Solution Preview] - [List Items are scrollable but heading is fixed]
I have very small & straight forward answer, see putting listview inside column will force column to expand infinitely, which is basically an error thing.
Now if you put physics: NeverScrollableScrollPhysics(),
like others suggested, in listview then whats the point of having listview if you disable scrolling inside it..
There is an easy fix, frankly I landed on this by hit and trial. Let me give you small explanation after code.
Column(
children: [
Text(
"All Bookings",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Colors.brown[700]),
),
Expanded(
child: Container(
margin: EdgeInsets.only(top: 24),
child: ListView.builder(
itemCount: 30,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text("List Item ${index + 1}"),
),
),
),
),
],
)
I had requirement to have title inside Column as first element & then put a Listview so that user can have scrolling list. This is a generic kind of requirement. You can put this in Bottom Sheet or Modal too.
Code Explanation:
Please correct me if I am wrong anywhere or if this code doesn't work (it works as of now without errors :)
Upvotes: 7
Reputation: 3223
You need to do 2 things:
Column
inside SingleChildScrollView
shrinkWrap: true
and physics: NeverScrollableScrollPhysics()
in ListView
Why it works:
As I uderstand, NeverScrollableScrollPhysics
disable scrolling of ListView
.
So, scroll works with SingleChildScrollView
.
If I am wrong, comment bellow.
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Filter'),
ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: rides.length,
itemBuilder: (BuildContext context, int index) {
# return some widget
}
),
Upvotes: 7
Reputation: 363
Also, you can try use CustomScrollView
CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final OrderModel order = _orders[index];
return Container(
margin: const EdgeInsets.symmetric(
vertical: 8,
),
child: _buildOrderCard(order, size, context),
);
},
childCount: _orders.length,
),
),
SliverToBoxAdapter(
child: _buildPreloader(context),
),
],
);
Tip: _buildPreloader
return CircularProgressIndicator
or Text
In my case i want to show under ListView some widgets. Use Column
does't work me, because widgets around ListView inside Column showing always "up" on the screen, like "position absolute"
Sorry for my bad english
Upvotes: 1
Reputation: 1084
Column(
children: <Widget>[
Text('Leading text widget'),
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
ListTile(
leading: Icon(Icons.map),
title: Text('Map'),
),
ListTile(
leading: Icon(Icons.photo_album),
title: Text('Album'),
),
ListTile(
leading: Icon(Icons.phone),
title: Text('Phone'),
),
],
),
Text('More widget'),
],
);
just use
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
properties in listView
Upvotes: 6
Reputation: 1
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Login / Signup"),
),
body: new Container(
child: new Center(
child: ListView(
//mainAxisAlignment: MainAxisAlignment.center,
scrollDirection: Axis.vertical,
children: <Widget>[
new TextField(
decoration: new InputDecoration(
hintText: "E M A I L A D D R E S S"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(obscureText: true,
decoration: new InputDecoration(
hintText: "P A S S W O R D"
),
),
new Padding(padding: new EdgeInsets.all(15.00)),
new TextField(decoration: new InputDecoration(
hintText: "U S E R N A M E"
),),
new RaisedButton(onPressed: null,
child: new Text("SIGNUP"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new RaisedButton(onPressed: null,
child: new Text("LOGIN"),),
new Padding(padding: new EdgeInsets.all(15.00)),
new ListView(scrollDirection: Axis.horizontal,
children: <Widget>[
new RaisedButton(onPressed: null,
child: new Text("Facebook"),),
new Padding(padding: new EdgeInsets.all(5.00)),
new RaisedButton(onPressed: null,
child: new Text("Google"),)
],)
],
),
),
margin: new EdgeInsets.all(15.00),
),
),
);
Upvotes: 0
Reputation: 6986
Try using Slivers:
Container(
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate(
[
HeaderWidget("Header 1"),
HeaderWidget("Header 2"),
HeaderWidget("Header 3"),
HeaderWidget("Header 4"),
],
),
),
SliverList(
delegate: SliverChildListDelegate(
[
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
BodyWidget(Colors.green),
BodyWidget(Colors.orange),
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
],
),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
delegate: SliverChildListDelegate(
[
BodyWidget(Colors.blue),
BodyWidget(Colors.green),
BodyWidget(Colors.yellow),
BodyWidget(Colors.orange),
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
],
),
),
],
),
),
)
Upvotes: 0
Reputation: 191
You can use Flex
and Flexible
widgets. for example:
Flex(
direction: Axis.vertical,
children: <Widget>[
... other widgets ...
Flexible(
flex: 1,
child: ListView.builder(
itemCount: ...,
itemBuilder: (context, index) {
...
},
),
),
],
);
Upvotes: 9
Reputation: 603
As have been mentioned by others above,Wrap listview with Expanded is the solution.
But when you deal with nested Columns you will also need to limit your ListView to a certain height (faced this problem a lot).
If anyone have another solution please, mention in comment or add answer.
Example
SingleChildScrollView(
child: Column(
children: <Widget>[
Image(image: ),//<< any widgets added
SizedBox(),
Column(
children: <Widget>[
Text('header'), //<< any widgets added
Expanded(child:
ListView.builder(
//here your code
scrollDirection: Axis.horizontal,
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
return Container();
}
)
),
Divider(),//<< any widgets added
],
),
],
),
);
Upvotes: 14
Reputation: 586
Actually, when you read docs the ListView should be inside Expanded Widget so it can work.
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Align(
child: PayableWidget(),
),
Expanded(
child: _myListView(context),
)
],
));
}
Upvotes: 11
Reputation: 13471
I have SingleChildScrollView
as a parent, and one Column
Widget and then List View Widget as last child.
Adding these properties in List View Worked for me.
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
Upvotes: 49