A regular vertical ListView would fill all the space on both axes, and shrinkWrap would make it shrink on the main axis, however, how can I make it shrink on the cross axis, just taking as much space as its biggest child needs, while being constrained by the maximum available horizontal space? Something like this:
You can't.
Children are laid out only when they are visible on screen. Which means ListView don't know the maximum cross-axis size of it's children.
If you have a small amount of children you can instead replace ListView by SingleChildSrollView and then add as a child a Column containing all your children
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
color: Colors.red,
width: 50.0,
height: 200.0,
),
Container(
color: Colors.yellow,
width: 100.0,
height: 200.0,
),
Container(
color: Colors.red,
width: 50.0,
height: 200.0,
),
Container(
color: Colors.red,
width: 50.0,
height: 200.0,
),
],
),
),
Related
How do I align one widget of a column in the center and put the rest around it?
If I had a Container or so that holds the three input fields and the button and another one that is the box above. How do I align the Container in the middle and put the box in the remaining space without moving the center container?
I tried using Expanded or Flexible but couldnt figure out how to align the widgets in that kind of way.
You can use Column like this:
Column(
children: [
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 40,
width: 40,
color: Colors.yellow,
),
)),
Container(
color: Colors.red,
height: 100,
width: double.infinity,
),
Expanded(
child: Align(
alignment: Alignment.topCenter,
child: Container(
height: 40,
width: 40,
color: Colors.green,
),
)),
],
),
I'm trying to create a custom widget and it makes use of the Stack widget. When I wrap the Stack's children using the Positined widget, the stack hugs the children that are not positioned. When I try to use the Align widget for more precise placement the stack expands to fill all the available space.
I'm trying to avoid using any widget with a fixed size, i.e. Container or SizedBox, as the parent for the Stack widget.
Is there a way to prevent the stack from filling all the available space or work around this that archives the same result?
I'm trying to position a child to the top center of the Stack as an example and this is where I am right now:
Using the Positined widget (I have to try multiple time to get the center position and sometimes its still off):
Positioned(
top: 0,
left: 80,
child: child,
);
Using the Align widget:
Align(
alignment: Alignment.topCenter,
child: child,
);
This should be the result using the Align widget:
Align(
alignment: Alignment.topCenter,
child: child,
);
You can set Stack's alignment to topCenter, Try this:
Stack(
alignment: Alignment.topCenter, // <=== add this
children: [
Container(
color: Colors.grey,
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min, // <=== add this
children: [
Container(
color: Colors.amber,
height: 30,
width: 30,
),
Container(
color: Colors.green,
height: 30,
width: 30,
),
Container(
color: Colors.blue,
height: 30,
width: 30,
),
Container(
color: Colors.yellow,
height: 30,
width: 30,
),
],
),
),
Container(
color: Colors.red,
height: 30,
width: 30,
)
],
)
Note: make sure you set Row's mainAxisSize to min.
I have these three containers. That the first one needs to grow to cater for the children that will be in it. The second one could have a fixed height say a flex factor of 1, while the third one has a fixed height too say flex of 2. The whole of this screen can be scrollable. It actually has to be scrollable since the children of the first container can be a lot.
Note: the children of the first container will have a fixed height, the container will house a listview or column which will have fixed height children, say containers each of 50.0. How do I achieve this, especially the 'growability' of the first container, while maintaining the heights of the other containers.
What I have currently is
SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: ListView(
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.blueAccent[200],
child: Column(children: [
Container(
height: 100.0,
color: Colors.greenAccent[200],
),
Container(
height: 100.0,
color: Colors.purpleAccent[200],
),
Container(
height: 100.0,
color: Colors.orangeAccent[200],
)
]),
)),
Expanded(
flex: 1,
child: Container(
color: Colors.redAccent[100],
),
),
Expanded(
flex: 1,
child: Container(
//height: 120.0,
color: Colors.redAccent[400],
),
),
],
),
),
),
Which just brings up lots and lots of errors, does not matter how I lay it out using flexibles and Expanded widgets. Again, I don't need the first container to scroll internally, it should grow according to the number of children in it, while the rest of the two containers maintain their heights.
You can not user Expanded or Flexible inside a scrollable widget since the child of Expanded will then get a height of infinity and the height of the child of Flexible will not get its parents height to compare with.
You can set the height of the bottom two containers based on the height of the screen.
SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: ListView(
children: [
Container(
color: Colors.blueAccent[200],
child: Column(
children: [
Container(
height: 100.0,
color: Colors.greenAccent[200],
),
Container(
height: 100.0,
color: Colors.purpleAccent[200],
),
Container(
height: 100.0,
color: Colors.orangeAccent[200],
)
],
),
),
Container(
// 33 % of the screen height
height: .33 * MediaQuery.of(context).size.height,
color: Colors.redAccent[100],
),
Container(
// 33 % of the screen height
height: .33 * MediaQuery.of(context).size.height,
color: Colors.redAccent[400],
),
],
),
),
),
I try to put a widget offscreen and then create a slide animation to transition inside the screen. I encountered a problem with Align widget which seems to not work as documentation states (Align, Alignment).
I have a Widget (same size as the screen) and I want to position it outside of the screen (on the left side). By their documentation, an Align widget with Alignment(-3, 0) should do the trick but, when I experimented, Align acted very different based on the child size.
I created 3 examples where I have a parent container (which takes place of the screen container) and a child container which represents the widget I want to align.
In #align1 the child moved outside of the parent container but not enough, per their documentation it should be moved by the entire width of the parent widget.
The distance from -1.0 to +1.0 is the distance from one side of the rectangle to the other side of the rectangle. Therefore, 2.0 units horizontally (or vertically) is equivalent to the width (or height) of the rectangle.
In #align2 the child moved very little and in #align3 not 'moved' at all even if the x(-10 or -100) is smaller.
Column(
children: [
// #align1
Container(
margin: EdgeInsets.only(top: 50),
color: Colors.redAccent,
width: 100,
height: 100,
child: Align(
alignment: Alignment(-3, 0),
child: Container(
color: Colors.black,
width: 50,
height: 50,
),
),
),
// #align2
Container(
color: Colors.amberAccent,
width: 100,
height: 100,
child: Align(
alignment: Alignment(-3, 0),
child: Container(
color: Colors.deepPurpleAccent,
width: 90,
height: 50,
),
),
),
// #align3
Container(
color: Colors.greenAccent,
width: 100,
height: 100,
child: Align(
alignment: Alignment(-3, 0),
child: Container(
color: Colors.deepOrange,
width: 100,
height: 50,
),
),
),
],
);
What I understood wrong and how can I accomplish what I want ?
I am adding a Container inside Column. I have given Container fixed width 60% of device width and height is 30% of device height. For height it is reflecting good but width covering whole parent.
I am not sure what I am doing wrong.
Here is my code:
Scaffold(
body: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height*.30,
child: Container(
width: MediaQuery.of(context).size.width*.20,
height: 40,
child: Text('test'),
color: Colors.blueAccent,
),
),
Expanded(
child: ListView(
children: chatList.map((chatModel) {
return ChatTileWidget(chatModel: chatModel,);
}).toList(),
),
)
],
),
);
Constraints in Flutter works different than usual. If you want to give height and width to the child, it will usually follows its parents constraints.
To read more about Constraints in Flutter: Understanding Constraints.
To get what you want, you need to use Align and set the alignment property to your preferred position. Here is an example for you. I have wrapped your inner Container with an Align widget and set the alignment to topLeft so it doesn't take it's parent height and width:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.3,
child: Align(
alignment: Alignment.topLeft,
child: Container(
height: 40.0,
color: Colors.blueAccent,
width: MediaQuery.of(context).size.width * 0.2,
child: Text('test')
)
)
)
]
)
RESULT
To know more about Align, please see this: Align Class.