Set the space between Elements in Row Flutter
Asked Answered
F

15

208

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?

Fiber answered 4/11, 2018 at 14:14 Comment(5)
check, Flutter — Row/Column Cheat SheetBermuda
Did u try: MainAxisAlignment.spaceAround?Yusuk
Add sizedbox. Check this mightytechno.com/flutter-row-widgetMixed
just add a sizedbox if you want a fixed amount of space.Livelihood
solution using package spaces2: see this postGive
T
32

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),
                )
              ],
            ),
          ),
Tyrant answered 4/11, 2018 at 14:33 Comment(3)
Thanks for your help. With GestureDetector everything works great.Fiber
One downside of using GestureDetector, you have to manage ripple effect (button feedback) on your own and without having this, you end up having a weird UXInterscholastic
Replace "GestureDetector" with "InkWell" and you will get back at least some kind of ripple effect.Ruble
I
406

There are many ways of doing it, I'm listing a few here:

  1. Use SizedBox if you want to set some specific space

    Row(
      children: <Widget>[
        Text("1"),
        SizedBox(width: 50), // give it width
        Text("2"),
      ],
    )
    

    enter image description here


  1. Use Spacer if you want both to be as far apart as possible.

    Row(
      children: <Widget>[
        Text("1"),
        Spacer(), // use Spacer
        Text("2"),
      ],
    )
    

    enter image description here


  1. Use mainAxisAlignment according to your needs:

    Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, // use whichever suits your need
      children: <Widget>[
        Text("1"),
        Text("2"),
      ],
    )
    

    enter image description here


  1. Use Wrap instead of Row and give some spacing

    Wrap(
      spacing: 100, // set spacing here
      children: <Widget>[
        Text("1"),
        Text("2"),
      ],
    )
    

    enter image description here


  1. Use Wrap instead of Row and give it alignment

    Wrap(
      alignment: WrapAlignment.spaceAround, // set your alignment
      children: <Widget>[
        Text("1"),
        Text("2"),
      ],
    )
    

    enter image description here

Interscholastic answered 4/11, 2018 at 14:53 Comment(3)
Missing flex :)Lapointe
I think Flex isn't necessary as per Flutter docs: If you know the main axis in advance, then consider using a Row (if it's horizontal) or Column (if it's vertical) instead, because that will be less verboseTimberwork
use what, if I want both to be as close as possible.Suntan
S
205

MainAxisAlignment

start - Place the children as close to the start of the main axis as possible.

enter image description here

end - Place the children as close to the end of the main axis as possible.

enter image description here

center - Place the children as close to the middle of the main axis as possible.

enter image description here

spaceBetween - Place the free space evenly between the children.

enter image description here

spaceAround - Place the free space evenly between the children as well as half of that space before and after the first and last child.

enter image description here

spaceEvenly - Place the free space evenly between the children as well as before and after the first and last child.

enter image description here

Example:

  child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Text('Row1'),
          Text('Row2')
        ],
      )
Spume answered 22/11, 2018 at 17:30 Comment(1)
I'm looking for a solution where both of my text are of different length, so when I place them in center close to each other, together they seem off-center.Wastepaper
T
32

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),
                )
              ],
            ),
          ),
Tyrant answered 4/11, 2018 at 14:33 Comment(3)
Thanks for your help. With GestureDetector everything works great.Fiber
One downside of using GestureDetector, you have to manage ripple effect (button feedback) on your own and without having this, you end up having a weird UXInterscholastic
Replace "GestureDetector" with "InkWell" and you will get back at least some kind of ripple effect.Ruble
M
26

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),
    ]
  );
Magisterial answered 16/4, 2019 at 22:43 Comment(0)
T
6

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'),
        ),
      )
    ],
  ),
Timmie answered 16/4, 2020 at 15:21 Comment(0)
H
6
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

Hargett answered 25/11, 2020 at 8:31 Comment(1)
Since you are going down this road, why not just use SizedBox(width: 10)....Upolu
I
5

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,
          )
        ],
      ),
    ),  
Indicatory answered 19/9, 2020 at 8:41 Comment(0)
J
2

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://mcmap.net/q/128987/-how-do-i-remove-flutter-iconbutton-big-padding

Joerg answered 6/3, 2020 at 14:16 Comment(1)
Thank you I cant believe they don't even have a padding property. I spent almost half an hour trying to figure out this imaginary space!!!Fighter
D
2

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(),
    );
  }
}
Deitz answered 18/7, 2023 at 10:8 Comment(0)
A
2

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.

Adsorb answered 1/10, 2023 at 16:53 Comment(0)
O
0

use this on every child of the row to give them equal and symmetric space :-

Flexible(
     flex: 1,
     fit: FlexFit.tight,
     child: ChildWidget()
)
Outrange answered 6/9, 2023 at 19:5 Comment(0)
V
0

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.

Vendetta answered 16/9, 2023 at 10:6 Comment(0)
H
0

If Row is inside your Appbar's Leading Widget (or any constrained in width Widget)

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:
[...]
Hebbe answered 26/9, 2023 at 13:59 Comment(0)
D
-1

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);
Dwinnell answered 26/4, 2023 at 11:43 Comment(0)
C
-1

Don't forget the .devide(T) function for a list of widgets. It's my go-to for a constant spacing.

Row(
 children:[
    Text('1'),
    Text('2'),
    Text('3'),
  ].divide(SizedBox(
    width: 30,
  ),
),
Cureton answered 21/3 at 17:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.