Space between Column's children in Flutter
DartFlutterFlutter LayoutDart Problem Overview
I have a Column
widget with two TextField
widgets as children and I want to have some space between both of them.
I already tried mainAxisAlignment: MainAxisAlignment.spaceAround
, but the result was not what I wanted.
Dart Solutions
Solution 1 - Dart
You can use Padding
widget in between those two widget or wrap those widgets with Padding
widget.
Update
SizedBox widget can be use in between two widget to add space between two widget and it makes code more readable than padding widget.
Ex:
Column(
children: <Widget>[
Widget1(),
SizedBox(height: 10),
Widget2(),
],
),
Solution 2 - Dart
You can put a SizedBox
with a specific height
between the widgets, like so:
Column(
children: <Widget>[
FirstWidget(),
SizedBox(height: 100),
SecondWidget(),
],
),
Why to prefer this over wrapping the widgets in Padding
? Readability! There is less visual boilerplate, less indention and the code follows the typical reading-order.
Solution 3 - Dart
you can use Wrap()
widget instead Column()
to add space between child widgets.And use spacing property to give equal spacing between children
Wrap(
spacing: 20, // to apply margin in the main axis of the wrap
runSpacing: 20, // to apply margin in the cross axis of the wrap
children: <Widget>[
Text('child 1'),
Text('child 2')
]
)
Solution 4 - Dart
There are many ways of doing it, I'm listing a few here.
-
Use
SizedBox
and provide some height:Column( children: <Widget>[ Widget1(), SizedBox(height: 10), // <-- Set height Widget2(), ], )
-
Use
Spacer
Column( children: <Widget>[ Widget1(), Spacer(), // <-- Spacer Widget2(), ], )
-
Use
Expanded
Column( children: <Widget>[ Widget1(), Expanded(child: SizedBox.shrink()), // <-- Expanded Widget2(), ], )
-
Set
mainAxisAlignment
Column( mainAxisAlignment: MainAxisAlignment.spaceAround, // <-- alignments children: <Widget>[ Widget1(), Widget2(), ], )
-
Use
Wrap
Wrap( direction: Axis.vertical, spacing: 20, // <-- Spacing between children children: <Widget>[ Widget1(), Widget2(), ], )
Solution 5 - Dart
Just use padding to wrap it like this:
Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Text('Hello World!'),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Text('Hello World2!'),
)
]);
You can also use Container(padding...) or SizeBox(height: x.x). The last one is the most common but it will depents of how you want to manage the space of your widgets, I like to use padding if the space is part of the widget indeed and use sizebox for lists for example.
Solution 6 - Dart
I don't see this solution here, so just for the sake of completeness I'll post it.
You can also wrap children with Padding
using map
:
Column(
children: [Text('child 1'), Text('child 2')]
.map(
(e) => Padding(
padding: const EdgeInsets.all(8),
child: e,
),
)
.toList(),
);
Solution 7 - Dart
Column(
children: <Widget>[
FirstWidget(),
Spacer(),
SecondWidget(),
]
)
Spacer creates a flexible space to insert into a [Flexible] widget. (Like a column)
Solution 8 - Dart
The same way SizedBox is used above for the purpose of code readability, you can use the Padding widget in the same manner and not have to make it a parent widget to any of the Column's children
Column(
children: <Widget>[
FirstWidget(),
Padding(padding: EdgeInsets.only(top: 40.0)),
SecondWidget(),
]
)
Solution 9 - Dart
If you don't wanna wrap Padding with every widget or repeat SizedBox.
Try this:
Column(
children: [
Widget(),
Widget(),
Widget(),
Widget(),
]
.map((e) => Padding(
child: e,
padding: const EdgeInsets.symmetric(vertical: 10),
))
.toList(),
),
That will warp all the widgets with padding without repetition.
Solution 10 - Dart
You can solve this problem in different way.
> If you use Row/Column then you have to use mainAxisAlignment: > MainAxisAlignment.spaceEvenly > > If you use Wrap Widget you have to use runSpacing: 5, spacing: > 10, > > In anywhere you can use SizeBox()
Solution 11 - Dart
Columns Has no height by default, You can Wrap your Column to the Container and add the specific height to your Container. Then You can use something like below:
Container(
width: double.infinity,//Your desire Width
height: height,//Your desire Height
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('One'),
Text('Two')
],
),
),
Solution 12 - Dart
You can also use a helper function to add spacing after each child.
List<Widget> childrenWithSpacing({
@required List<Widget> children,
double spacing = 8,
}) {
final space = Container(width: spacing, height: spacing);
return children.expand((widget) => [widget, space]).toList();
}
So then, the returned list may be used as a children of a column
Column(
children: childrenWithSpacing(
spacing: 14,
children: [
Text('This becomes a text with an adjacent spacing'),
if (true == true) Text('Also, makes it easy to add conditional widgets'),
],
),
);
I'm not sure though if it's wrong or have a performance penalty to run the children through a helper function for the same goal?
Solution 13 - Dart
Column(children: <Widget>[
Container(margin: EdgeInsets.only(top:12, child: yourWidget)),
Container(margin: EdgeInsets.only(top:12, child: yourWidget))
]);
Solution 14 - Dart
I also wish there was some built-in way in Flutter to do this. Like a parameter you could pass to Column or Row. Sometimes you don't want padding around every element but you want space between them. Especially if you have more than two children, it's kind of tedious to write something like
const double gap = 10;
return Column(
children: [
Text('Child 1'),
SizedBox(height: gap),
Text('Child 2'),
SizedBox(height: gap),
Text('Child 3'),
SizedBox(height: gap),
Text('Child 4'),
],
);
However, I've came up with one quick (not perfect) solution:
Add this somewhere in your project (only once):
extension ListSpaceBetweenExtension on List<Widget> {
List<Widget> withSpaceBetween({double? width, double? height}) => [
for (int i = 0; i < this.length; i++)
...[
if (i > 0)
SizedBox(width: width, height: height),
this[i],
],
];
}
And from now on whenever you have a Row or a Column, you can write
Column(
children: [
Text('Child 1'),
Text('Child 2'),
Text('Child 3'),
Text('Child 4'),
].withSpaceBetween(height: 10),
),
When using Row you'll have to replace 'height' with 'width'.
Solution 15 - Dart
You may have to use SizedBox() widget between your column's children. Hope that'll be usefull
Solution 16 - Dart
It's best to use the Wrap widget instead of a column or row.
Wrap( spacing: 10, runSpacing: 10, children:[], )
Solution 17 - Dart
Column widget doesn't have its own height, it just expanded as we added inside the children widget. for if you need the same space between multiple widgets so,
Container(
width: double.infinity,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('One'),
Text('Two'),
Text('Three'),
Text('Four')
],
),
),
or just added custom space between them by using SizeBox, Spacer, or widget, like this
Column(
children: <Widget>[
Text('One'),
SizedBox(height: 20),
Text('Two'),
SizedBox(height: 40),
Text('Three'),
SizedBox(height: 30),
Text('Four')
],
),
Solution 18 - Dart
The sized box will not help in the case, the phone is in landscape mode.
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: Color(0xFF1D1E33),
borderRadius: BorderRadius.circular(10.0),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: Color(0xFF1D1E33),
borderRadius: BorderRadius.circular(10.0),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: Color(0xFF1D1E33),
borderRadius: BorderRadius.circular(10.0),
),
),
),
],
)
Solution 19 - Dart
Here's another option involving a for loop.
Column(
children: <Widget>[
for (var i = 0; i < widgets.length; i++)
Column(
children: [
widgets[i], // The widget you want to create or place goes here.
SizedBox(height: 10) // Any kind of padding or other widgets you want to put.
])
],
),
Solution 20 - Dart
You can try this :
import 'package:flutter/material.dart';
class CustomColumn extends Column {
CustomColumn({
Key? key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection? textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline? textBaseline,
List children = const [],
EdgeInsetsGeometry? rowPadding,
}) : super(
children: children.map((e) => Padding(padding : rowPadding ?? EdgeInsets.only(bottom:12), child : e)).toList(),
key: key,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
);
}
class CustomColumn extends Column {
CustomColumn({
Key? key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection? textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline? textBaseline,
List children = const [],
EdgeInsetsGeometry? rowPadding,
}) : super(
children: children.map((e) => Padding(padding : rowPadding ?? EdgeInsets.only(bottom:12), child : e)).toList(),
key: key,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
);
}
and call
CustomColumn(children: [
item1,
item2,
item3,
])
Solution 21 - Dart
You can use Padding to wrap each child widget, and then set the top
or bottom
of Padding.
If you don’t want to write a lot of the same numbers, you can do it like this:
Column(
children: [
child1,
child2,
...,
childN
].map((e) => Padding(padding: EdgeInsets.only(top: 10), child: e)).toList()
);