Reputation: 2339
Code:
new Container(
alignment: FractionalOffset.center,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton(
child: new Text('Don\'t have an account?', style: new TextStyle(color: Color(0xFF2E3233))),
),
new FlatButton(
child: new Text('Register.', style: new TextStyle(color: Color(0xFF84A2AF), fontWeight: FontWeight.bold),),
onPressed: moveToRegister,
)
],
),
),
And here is the result: https://dartpad.dev/?id=6bbfc6139bdf32aa7b47eebcdf9623ba
How to fix that the two FlatButton
elements are side by side without space between the center of the screen width?
Upvotes: 215
Views: 395448
Reputation: 333
Starting from Flutter 3.27, you can use the spacing
property in the Row
widget to easily add uniform spacing between its children. This eliminates the need for adding multiple SizedBox
widgets manually, making your layout cleaner and more concise.
Here's an example:
Row(
spacing: 10, // <-- Add uniform spacing between children
children: <Widget>[
Icon(Icons.home),
Icon(Icons.star),
Icon(Icons.settings),
],
)
Row spacing
:Row
widget, no extra widgets required.This is the recommended approach if you are using Flutter 3.27 or later. For earlier versions, you would need alternatives like SizedBox
or Spacer
.
Upvotes: 1
Reputation: 2530
If you have an arbitrary long list and wish to insert a SizedBox
in between each element:
Column(
children: [
const Text("hello"),
const Text("hello2"),
const Text("hello3"),
].expand((x) => [const SizedBox(height: 10), x]).skip(1).toList());
}
This inserts a SizedBox
before every element, then ignores the one inserted before the first one.
Upvotes: 4
Reputation: 11219
The appbar leading widget is constrained in width, so whatever solution I was trying it would not work.
Fortunately the appbar has the leadingWidth
property (defaulting to 56), so just increase it as you need.
As a general rule, try to check if your Row is the child of a widget which has a constrained width.
Scaffold(
appBar: AppBar(leadingWidth: 112, // now the spacing between items in the Row will work!
leading: Builder(builder: (BuildContext context) {
return Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children:
[...]
Upvotes: 0
Reputation: 1184
A more generic version of what Luke Stanyer suggested is this extension:
extension SpacingExtension on Flex {
Flex withSpacing({
double spacing = 0.0,
}) {
var spacedChildren = this
.children
.expand((widget) => [widget, SizedBox.square(dimension: spacing)])
.toList();
// Remove the extra SizedBox
if (spacedChildren.isNotEmpty) spacedChildren.removeLast();
return Flex(
direction: this.direction,
children: spacedChildren,
crossAxisAlignment: this.crossAxisAlignment,
mainAxisAlignment: this.mainAxisAlignment,
mainAxisSize: this.mainAxisSize,
textDirection: this.textDirection,
verticalDirection: this.verticalDirection,
textBaseline: this.textBaseline,
key: this.key,
);
}
}
It works for both Columns and Rows.
Upvotes: 0
Reputation: 31
use this on every child of the row to give them equal and symmetric space :-
Flexible(
flex: 1,
fit: FlexFit.tight,
child: ChildWidget()
)
Upvotes: 0
Reputation: 1484
With a column extension
, use like:
Column.withSpacing(
spacing: 20,
children: [
Text('One'),
Text('Two'),
],
)
Extension:
import 'package:flutter/material.dart';
extension SpacingExtension on Column {
static Column withSpacing({
Key? key,
required List<Widget> children,
int spacing = 10,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection? textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline? textBaseline,
}) {
var spacedChildren = children.expand((widget) => [widget, SizedBox(height: spacing.toDouble())]).toList();
spacedChildren.removeLast(); // Remove the extra SizedBox
return Column(
key: key,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
children: spacedChildren,
);
}
}
Or as a widget:
Use:
SpacingColumn(
spacing: 20,
children: [
Text('One'),
Text('Two'),
],
)
Widget:
import 'package:flutter/material.dart';
class SpacingColumn extends StatelessWidget {
final List<Widget> children;
final int spacing;
final MainAxisAlignment mainAxisAlignment;
final MainAxisSize mainAxisSize;
final CrossAxisAlignment crossAxisAlignment;
final TextDirection? textDirection;
final VerticalDirection verticalDirection;
final TextBaseline? textBaseline;
SpacingColumn({
Key? key,
required this.children,
this.spacing = 10,
this.mainAxisAlignment = MainAxisAlignment.start,
this.mainAxisSize = MainAxisSize.max,
this.crossAxisAlignment = CrossAxisAlignment.center,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
this.textBaseline,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
children: children.expand((widget) => [widget, SizedBox(height: spacing.toDouble())]).toList()..removeLast(),
);
}
}
Upvotes: 5
Reputation: 1493
Here the another Custom method we can use everywhere for both Horizontal and Vertical Spacing
This method for custom Horizontal spacing
SizedBox horizontalSpace(space) => SizedBox(width: space);
This method for custom Vertical spacing
SizedBox verticalSpace(space) => SizedBox(height: space);
Upvotes: -1
Reputation: 4780
You can use Spacers if all you want is a little bit of spacing between items in a row. The example below centers 2 Text widgets within a row with some spacing between them.
Spacer creates an adjustable, empty spacer that can be used to tune the spacing between widgets in a Flex
container, like Row
or Column
.
In a row
, if we want to put space between two widgets such that it occupies all remaining space.
widget = Row (
children: <Widget>[
Spacer(flex: 20),
Text(
"Item #1",
),
Spacer(), // Defaults to flex: 1
Text(
"Item #2",
),
Spacer(flex: 20),
]
);
Upvotes: 26
Reputation: 1278
Row(
children: <Widget>[
Flexible(
child: TextFormField()),
Container(width: 20, height: 20),
Flexible(
child: TextFormField())
])
This works for me, there are 3 widgets inside row: Flexible, Container, Flexible
Upvotes: 6
Reputation: 160
Just add "Container(width: 5, color: Colors.transparent)," between elements
new Container(
alignment: FractionalOffset.center,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton(
child: new Text('Don\'t have an account?', style: new TextStyle(color: Color(0xFF2E3233))),
),
Container(width: 5, color: Colors.transparent),
new FlatButton(
child: new Text('Register.', style: new TextStyle(color: Color(0xFF84A2AF), fontWeight: FontWeight.bold),),
onPressed: moveToRegister,
)
],
),
),
Upvotes: 5
Reputation: 1790
To make an exact spacing, I use Padding
. An example with two images:
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Image.asset('images/user1.png'),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Image.asset('images/user2.png'),
),
)
],
),
Upvotes: 6
Reputation: 1321
I believe the original post was about removing the space between the buttons in a row, not adding space.
The trick is that the minimum space between the buttons was due to padding built into the buttons as part of the material design specification.
So, don't use buttons! But a GestureDetector instead. This widget type give the onClick
/ onTap
functionality but without the styling.
See this post for an example.
https://stackoverflow.com/a/56001817/766115
Upvotes: 2
Reputation: 267404
There are many ways of doing it, I'm listing a few here:
Use SizedBox
if you want to set some specific space
Row(
children: <Widget>[
Text("1"),
SizedBox(width: 50), // give it width
Text("2"),
],
)
Use Spacer
if you want both to be as far apart as possible.
Row(
children: <Widget>[
Text("1"),
Spacer(), // use Spacer
Text("2"),
],
)
Use mainAxisAlignment
according to your needs:
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // use whichever suits your need
children: <Widget>[
Text("1"),
Text("2"),
],
)
Use Wrap
instead of Row
and give some spacing
Wrap(
spacing: 100, // set spacing here
children: <Widget>[
Text("1"),
Text("2"),
],
)
Use Wrap
instead of Row
and give it alignment
Wrap(
alignment: WrapAlignment.spaceAround, // set your alignment
children: <Widget>[
Text("1"),
Text("2"),
],
)
Upvotes: 421
Reputation: 11534
MainAxisAlignment
start - Place the children as close to the start of the main axis as possible.
end - Place the children as close to the end of the main axis as possible.
center - Place the children as close to the middle of the main axis as possible.
spaceBetween - Place the free space evenly between the children.
spaceAround - Place the free space evenly between the children as well as half of that space before and after the first and last child.
spaceEvenly - Place the free space evenly between the children as well as before and after the first and last child.
Example:
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Row1'),
Text('Row2')
],
)
Upvotes: 206
Reputation: 51186
Removing Space-:
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: new Text('Don\'t have an account?',
style: new TextStyle(color: Color(0xFF2E3233))),
onTap: () {},
),
GestureDetector(
onTap: (){},
child: new Text(
'Register.',
style: new TextStyle(
color: Color(0xFF84A2AF), fontWeight: FontWeight.bold),
))
],
),
OR
GestureDetector(
onTap: (){},
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text('Don\'t have an account?',
style: new TextStyle(color: Color(0xFF2E3233))),
new Text(
'Register.',
style: new TextStyle(
color: Color(0xFF84A2AF), fontWeight: FontWeight.bold),
)
],
),
),
Upvotes: 33