No matter what I do I can't seem to adjust the height of a nested Container in my flutter app. It always seems to inherit the height of the parent Container. Everything I read online said to wrap the inner container with a Center(). I tried this but still ended up with the same issue.
final _recommendations = <String>["Embroidery", "Jewelry Making", "Tennis", "Hiking", "Disc Golf"];
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Container(
padding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 16.0),
height: 200,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _recommendations.length,
itemBuilder: (context, index) {
return Container(
width: 150,
height: 50,
child: Card(
color: Colors.blue,
child: Center(
child: Text(_recommendations[index])
)
)
);
}
)
)
);
Seems to me like the height of ListView is defined by its parent which is Container. So I expect ListView to have a height of 200. Then the height of Card should be defined by its parent container which gives a height of 50. However Card instead takes a height of 200...
Usually, a ListView widget tries to fill all the available space given by the parent element, even when the list items would require less space. You can disable this feature using shrinkWrap parameter of ListView as follow:\
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _recommendations.length,
shrinkWrap:true,
itemBuilder: (context, index) {
return Container(
width: 150,
height: 100,
child: Card(
color: Colors.blue,
child: Center(
child: Text(_recommendations[index])
)
)
);
}
)
Related
I'm currently using a custom widget similar to this chips_input library. However, I don't want to give the options view (the popup list) a static maximum height. What I want to achieve is to dynamically set a maximum height of screen height - popup y offset. In this way, bottom of the options view will be at the bottom of the screen and all of the content inside the options view will be visible through scrolling. Is there any that I can access the textfield's or options view's offset to calculate the height?
My autocomplete widget looks similar to this:
RawAutocomplete<T>(
...
optionsViewBuilder: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: textFieldWidth,
child: Material(
elevation: 16,
child: ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final T option = options.elementAt(index);
return suggestionBuilder(context, option);
},
),
),
),
),
);
You can do this by putting a height on your SizedBox that uses MediaQuery to get the screen height:
popupOffset = 20;
RawAutocomplete<T>(
...
optionsViewBuilder: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: textFieldWidth,
height: MediaQuery.of(context).size.height - popupOffset,
child: Material(
elevation: 16,
child: ListView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) {
final T option = options.elementAt(index);
return suggestionBuilder(context, option);
},
),
),
),
),
);
So basically I ListView.builder widget inside of a fixed container.
Container(
height: 500,
child: TabBarView(
children: [
Container(
height: 500,
color: Colors.red,
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 100,
itemBuilder: (context, index) {
return Center(child: Text("This is index $index"));
},
),
),
Center(child: Text("Second Tab")),
Center(child: Text("Third Tab")),
],
),
),
Issue:
The issue with this widget is that since it is inside a container of a fixed height, the content of the list is cut off. I want the list to scroll along with the rest of the page so I don't want to remove the shrinkWrap nor NeverScrollableScrollPhysics(). I want it so that the list takes up as much room as it needs.
Things I've tried:
Wrap the ListView with a Column: this causes the widget to overflow and when I add the SingleChildScrollView around that Column, it removes the functionality of the shrinkWrap and NeverScrollableScrollPhysics().
Checked this answer. The parent widget is actually a CustomScrollView and this widget is inside of a SliverToBoxAdapter. That's why the container has a fixed size in the first place.
What can I do to get the ListView to take up as much room as it want? Thank you!
Wrap your container with SingleChildScrollView and make scrollPhysics
SingleChildScrollView(
Container(
height: 500,
color: Colors.red,
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: 100,
itemBuilder: (context, index) {
return Center(child: Text("This is index $index"));
},
),
),
)
I want to show Listview underneath my two widgets but when i hot reload, nothing happens and if i run again, UI shows blank screen. If i remove Listview.builder it works fine.
Below is my code.
import 'package:flutter/material.dart';
import 'package:plant_clone/constants.dart';
import 'package:plant_clone/model/model.dart';
import 'package:plant_clone/screens/home/components/header_with_searchbox.dart';
import 'package:plant_clone/screens/home/components/title_with_more_btn.dart';
import 'package:plant_clone/viewmodel/recommended_plants_viewmodel.dart';
class Body extends StatelessWidget {
RecommendedPlantViewModel recommendedPlantViewModel =
new RecommendedPlantViewModel();
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
recommendedPlantViewModel.setWidgetsData();
return SingleChildScrollView(
child: Column(
children: [
HeaderWithSearchBox(size: size),
TitleWithMoreButton(
title: "Recommended",
press: () {},
),
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Card(
child: ListTile(
onTap: (){},
title: Text('Hello'),
),
);
})
],
),
);
}
}
It doesn't look like there's any other way than setting height constraint using a SizedBox that's wrapping a ListView.
Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: size.height,
child: ListView.builder(
...
),
),
],
)
https://flutter.dev/docs/cookbook/lists/horizontal-list
i think it happened because the list view should have a height,,
the esiest way is to test that put it inside a container and give a height to it..
and the second way is wrap the listview inside a Expanded widget and it will fix ..
if not then post the error from debug log
In order to make this to work, you must wrap your ListView with a Container and define the height property as it is part of a Column. You also need to wrap the widget returned by the itemBuilder with a Container and define the width property as the scrollDirection is set to Axis.horizontal.
Container(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Container(
width: 100,
child: Card(
child: ListTile(
onTap: () {},
title: Text('Hello'),
),
),
);
},
),
)
I have a horizontal ListView and depending on the app state, there might be 1-2 items in the list or many.
Now, I want to have the items centered as long as there are only a few available and scrolling is not needed. So far my items always stick to the left side as you can see in the ListView with the lime background color. That one I wanted centered, even if 2 or 3 items are visible, but with more, it shall scroll and then start at the left side with listing the items.
return Container(
color: Colors.lime,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: listItems));
the items itself are this:
Widget getPersonCircleWidget(BuildContext context, Person p) {
return Container(
color: Colors.transparent, //yellow,
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: CircularProfileAvatar('',
child: Image(
fit: BoxFit.cover,
image:
UserPhotoManager.singleton.getUserProfilePhoto(p.userId)),
borderColor: colorCirclePhotoBorder,
borderWidth: 2,
elevation: 10,
radius: 40,
onTap: () {
....
}),
),
);
}
Any idea how to solve this?
Just wrap your ListView with Center widget.
Center(
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: listItems.map<Widget>((a) => CircleAvatar(
child: Text(a))).toList(),
),
),
When ListView exceed available room on the screen it will automatically left aligned.
Try it on dartpad.
I have a page with container + listView. Now the listView is scrollable, but I would like the whole page to be scrollable. (so if the user scrolls, the container goes 'away')
Column(
children: <Widget>[
Container(
color: Colors.white.withOpacity(0.95),
width: 400,
height: 400,
child: Text("")),
ListView(
children: posts,
),
],
),
Is this possible, and how can it be achieved?
Thanks!
You can wrap the whole page with a SingleChildScrollView
here is an example:
SingleChildScrollView( // <- added
child: Column(
children: <Widget>[
Container(
color: Colors.white.withOpacity(0.95),
width: 400,
height: 400,
child: Text("")),
ListView(
shrinkWrap: true, // <- added
primary: false, // <- added
children: posts,
),
],
),
);
for more info about see this question
What if you don't use Column and use ListView.builder and
according to indexes you show the widget.
For example on 0 index you show the Container.
This way you don't have to use any different widget for scrolling
and as per your requirement the container will scroll with the list.
This way there is no chance that you will get any overflow error
like you were getting while using Column.
Plus point of ListView.builder is that your posts will be created lazily and that is efficient way of creating ListView in Flutter. No matter how many posts you have your UI will not lag.
This at first may look like a hack but according to your requirement that the container must also be able to get scrolled, this solution makes sense to me because Container can be considered as a first element of the list.
Let me know if it works for you or not.
Following is the working code for your reference:
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: posts.length + 1, // +1 because you are showing one extra widget.
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return Container(
color: Colors.white.withOpacity(0.95),
width: 400,
height: 400,
child: Text(""));
}
int numberOfExtraWidget = 1; // here we have 1 ExtraWidget i.e Container.
index = index - numberOfExtraWidget; // index of actual post.
return posts[index];
},
);
}
I hope this works for you, in case of any doubt please comment.
There are multiple ways you can achieve what you want. The only problem is that if you have large number of posts, listview with children posts, as shrinkWrap is set to true, will take time to calculate its required height, for that it will have to populate all of its children.
First
ListView(
children: <Widget>[
Container(
color: Colors.white.withOpacity(0.95),
width: 400,
height: 400,
child: Text("")),
ListView(
physics: NeverScrollableScrollPhysics(),
primary: false,
shrinkWrap: true,
children: posts,
),
),
],
),
Second
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
color: Colors.white.withOpacity(0.95),
width: 400,
height: 400,
child: Text("")),
ListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
primary: false,
children: posts,
),
],
),
),
use SingleChildScrollView then Container with hard coded container height, then list view builder, that should fix your issue.
I tried the following:
SingleChildScrollView(
child: Container(
height: 1000,
width: 400,
child: ListView(
children: <Widget>[
Container(
color: Colors.white.withOpacity(0.95),
width: 400,
height: 400,
child: Text("")),
ListView(
children: posts,
),
],
),
),
),
This works, but I would like that the container has a dynamic height and width? Is that possible? Thanks!