I am trying to nest the ListView in a Listview as per the below code, the Listview on top is scrolling horizontally and the nested ListView is scrolling vertically . for the nested ListView I am facing the error of
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 vertical viewport was given an unlimited amount of
horizontal space in which to expand.
How should I resolve it so that the Nested View is also shown in the below code?
new Container(
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
ListView(
scrollDirection:Axis.vertical,
children: <Widget>[new Container(
padding: EdgeInsets.fromLTRB(10, 20,10, 0),
width: screenSize.width,
child: new Column(
children: <Widget>[
Column(children: <Widget>[
Row(children: <Widget>[
Text('Text1'),
Text('Text1'),
],),
Row(children: <Widget>[
Text('Text1'),
Text('Text1'),
],),
],),
new Container(
//ERROR POINT
child: new ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: <Widget>[
new Container(
color: Colors.red,
width: screenSize.width,
child: new Center(
child: new Text(
'RED',
style: new TextStyle(
fontSize: 40.0,
color: Colors.white
),
),
),
),
new Container(
color: Colors.blue,
width: screenSize.width,
child: new Center(
child: new Text(
'BLUE',
style: new TextStyle(
fontSize: 40.0,
color: Colors.white
),
),
),
),
new Container(
color: Colors.orange,
width: screenSize.width,
child: new Center(
child: new Text(
'ORANGE',
style: new TextStyle(
fontSize: 40.0,
color: Colors.white
),
),
),
)
],
),
)
],
),
),],
),
new Container(
color: Colors.blue,
width: screenSize.width,
child: new Center(
child: new Text(
'BLUE',
style: new TextStyle(
fontSize: 40.0,
color: Colors.white
),
),
),
),
new Container(
color: Colors.orange,
width: screenSize.width,
child: new Center(
child: new Text(
'ORANGE',
style: new TextStyle(
fontSize: 40.0,
color: Colors.white
),
),
),
)
],
),
)
DO NOT wrap widgets with an empty Container
For nested ListView you have to constrain its width via either SizedBox or Container, like so:
ListView(
scrollDirection: Axis.horizontal,
children: [
SizedBox(
child: ListView(
children: [
Text('data'),
Text('data'),
Text('data'),
],
),
width: 300,
),
SizedBox(
child: ListView(
children: [
Text('data'),
Text('data'),
Text('data'),
],
),
width: 300,
),
SizedBox(
child: ListView(
children: [
Text('data'),
Text('data'),
Text('data'),
],
),
width: 300,
),
],
)
If you want to keep all nested scroll views positions you could wrap them in a SingleChildScrollView with Row, but it seems something is not quite right in your decision
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
SizedBox(
width: 200,
child: ListView.builder(
itemBuilder: (context, index) => Text('data $index'),
itemCount: 200,
),
),
SizedBox(
width: 200,
child: ListView.builder(
itemBuilder: (context, index) => Text('data $index'),
itemCount: 200,
),
),
SizedBox(
width: 300,
child: ListView.builder(
itemBuilder: (context, index) => Text('data $index'),
itemCount: 200,
),
),
SizedBox(
width: 300,
child: ListView.builder(
itemBuilder: (context, index) => Text('data $index'),
itemCount: 200,
),
),
SizedBox(
width: 300,
child: ListView.builder(itemBuilder: (context, index) => Text('data $index'), itemCount: 200),
),
SizedBox(
width: 300,
child: ListView.builder(itemBuilder: (context, index) => Text('data $index'), itemCount: 200),
),
],
),
)
Related
hi I have Row in flutter and I want add some widget on row with listview.builder, listview sort all item vertically. but I want show them horizontally. in the image below you can see my code and the result.so how can i change the listview.builder to horizontal?
You need set height for your ListView if you want to use it horizontally, and set scrollDirection to Axis.horizontal:
Row(
children: [
IconButton(onPressed: () {}, icon: Icon(Icons.chevron_left)),
Expanded(
child: SizedBox(
height: 10,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 12),
height: 10,
width: 10,
color: Colors.red,
);
},
itemCount: 10,
),
)),
IconButton(onPressed: () {}, icon: Icon(Icons.chevron_right)),
],
),
There is a property in listview scrollDirection you need to set for horizontal scrolling
scrollDirection: Axis.horizontal,
Widget build(BuildContext context) {
Widget horizontalList = new Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
height: 200.0,
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(width: 160.0, color: Colors.red,),
Container(width: 160.0, color: Colors.orange,),
Container(width: 160.0, color: Colors.pink,),
Container(width: 160.0, color: Colors.yellow,),
],
)
);
);
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: horizontalList,
),
);
it's possible to make listview in expand and fill the container without overflow the container, and shrink when listview is short of content without declare manual min or max height?
Code
Flexible(
fit: FlexFit.loose,
child: Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(kBoxRadius),
boxShadow: [kBoxShadow]),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DText(
"Aug 2021",
size: 12,
weight: FontWeight.bold,
),
SizedBox(height: 10),
Row(
children: dates,
),
SizedBox(height: 15),
Container(
height: 1,
color: Color(0xFFE7E7E7),
),
Container(
constraints:
BoxConstraints(minHeight: 0, maxHeight: 600),
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) {
return DText("Asd");
},
separatorBuilder: (_, __) {
return SizedBox(height: 10);
},
itemCount: 20,
),
)
],
),
),
)
Expectation
when the content is big
because i set manually max height.
Yes, it is possible using shrinkWrap: true. The code will be something like below,
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
color: Colors.red,
child: ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(title: Text('Apple')),
ListTile(title: Text('Orange')),
ListTile(title: Text('Banana')),
],
),
),
),
),
);
}
}
I have tried to return a list of widgets in horizontal direction, i want to expand widgets width dynamically. how can i achieve this. (Note: ListView.builder placed inside column)
ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: widget.playType.length,
itemBuilder: (BuildContext context, int index) {
return Flex(
direction: Axis.horizontal,
children: <Widget>[
Flexible(
child: InkWell(
onTap: () {},
child: Container(
padding: EdgeInsets.only(left: 10, right: 10),
color: colorSubMenuBg,
height: 45,
child: Align(
alignment: Alignment.center,
child: Text(
widget.playType[index],
style: CustomTextStyle.listTile4(context),
),
),
),
),
),
],
);
});
Expected output should be like this highlighted part:
Wrap Container( height: 70)in your ListViewBuilder()
like this
Container(
height: 70,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: widget.playType.length,
itemBuilder: (BuildContext context, int index) {
return Flex(
direction: Axis.horizontal,
children: <Widget>[
Flexible(
child: InkWell(
onTap: () {},
child: Container(
padding: EdgeInsets.only(left: 10, right: 10),
color: colorSubMenuBg,
height: 45,
child: Align(
alignment: Alignment.center,
child: Text(
widget.playType[index],
style: CustomTextStyle.listTile4(context),
),
),
),
),
),
],
);
}),
);```
Actual working code, i removed flex from ListView.builder and added width for ListItems and ListView.
var buttonListWidth = MediaQuery.of(context).size.width;
Container(
height: 45,
width: buttonListWidth,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: widget.playType.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
setState(() {});
},
child: Container(
color: colorSubMenuBg,
height: 45,
width: buttonListWidth / widget.playType.length,
child: Align(
alignment: Alignment.center,
child: Text(
widget.playType[index],
style: CustomTextStyle.listTile4(context),
),
),
),
);
}))
Try adding a Row over the ListView.builder and add mainAxisSize: MainAxisSize.min, property to that Row.
ItemExtent property of ListView.builder
itemExtent: MediaQuery.of(context).size.height / LENGHT,
I want to create a ListView and a Button to add items to the ListView.
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
Conversation conversation = teamMembers[index];
return SizedBox(
width: 42,
height: 42,
child: Avatar(
name: member.name,
profileUrl: member.profileUrl,
radius: 38,
),
);
},
itemCount: teamMembers.length,
),
),
InkWell(
onTap: () {
_showSheet();
},
child: Container(
width: 42,
height: 42,
decoration: new BoxDecoration(
color: Color(0xfff2f2f2),
borderRadius: BorderRadius.circular(28)),
child: Icon(Icons.add),
),
),
],
)
I'm getting the results as below for lesser number of items and more number of items. How can I make the + button closer to the ListView even if the list length is less.
List<Widget> _buttons = [];
Wrap(
spacing: 12.0, // horiz
runSpacing: 12.0, // vert
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
children: _buttons,
),
The solution to this issue is replacing the Expanded widget with Flexible widget.
Expanded actually is just a shorthand for Flexible. Flexible takes only the needed space, and Expanded takes all available space, respecting the flex factor.
Flexible with fit: FlexFit.loose which is the default one solves the problem. If the fit is FlexFit.loose, the child can be at most as large as the available space (but is allowed to be smaller)
So,
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
Conversation conversation = teamMembers[index];
return SizedBox(
width: 42,
height: 42,
child: Avatar(
name: member.name,
profileUrl: member.profileUrl,
radius: 38,
),
);
},
itemCount: teamMembers.length,
),
),
InkWell(
onTap: () {
_showSheet();
},
child: Container(
width: 42,
height: 42,
decoration: new BoxDecoration(
color: Color(0xfff2f2f2),
borderRadius: BorderRadius.circular(28)),
child: Icon(Icons.add),
),
),
],
)
is the solution.
I have a Card widget which includes Column with several other Widgets. One of them is Container.
Widget _renderWidget() {
return Column(
children: <Widget>[
Visibility(
visible: _isVisible,
child: Container(
width: 300,
height: 200,
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: ListView.builder(
itemCount: titles.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(icons[index]),
title: Text(titles[index]),
),
);
},
)),
),
],
);
}
Here, if I don't specify width and height I get error. But, is there a way to make them to fit parent element?
EDIT
Full code:
return ListView(
children: <Widget>[
Center(
child: Container(
child: Card(
margin: new EdgeInsets.all(20.0),
child: new Container(
margin: EdgeInsets.all(20.0),
width: double.infinity,
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: Column(
children: <Widget>[
FormBuilderDropdown(
onChanged: (t) {
setState(() {
text = t.vrsta;
});
},
validators: [FormBuilderValidators.required()],
items: user.map((v) {
return DropdownMenuItem(
value: v,
child: ListTile(
leading: Image.asset(
'assets/img/car.png',
width: 50,
height: 50,
),
title: Text("${v.vrsta}"),
));
}).toList(),
),
],
),
),
Container(child: _renderWidget()),
text.isEmpty
? Container()
: RaisedButton(
child: Text("Submit"),
onPressed: () {
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value.toString());
print(formData.startLocation);
getAutocomplete();
}
},
)
],
),
)),
),
),
],
);
}
Just set the height and width property of your Container to double.infinity
Solution Code:
Widget _renderWidget() {
return Column(
children: <Widget>[
Visibility(
visible: _isVisible,
child: Container(
width: double.infinity,
height: double.infinity,
decoration:
BoxDecoration(border: Border.all(color: Colors.grey)),
child: ListView.builder(
itemCount: titles.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(icons[index]),
title: Text(titles[index]),
),
);
},
)),
),
],
);
}
You are using ListView inside Column which is why you need to specify height in your Container to prevent errors.
The best way is to use Expanded or Flexible as parent of your ListView
Expanded(
child: ListView.builder(...)
)
Update:
Widget _renderWidget() {
return Column(
children: <Widget>[
Visibility(
visible: _isVisible,
child: Expanded(
child: ListView.builder(
itemCount: titles.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(icons[index]),
title: Text(titles[index]),
),
);
},
),
),
),
],
);
}