exilonX
exilonX

Reputation: 1761

Flutter wrapping Row in SingleChildScrollview ruins spaceBetween

I have aRow of buttons which have a parent of SingleChildScrollView, horizontally. After wrapping the SingleChildScrollView the elements of the row don't respect the mainAxisAlignment, specifically spaceBetween, they are together with not space in between...

How can I make the spaceBetween work again?

SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    mainAxisSize: MainAxisSize.max,
    children: const [
      TransportModeButton(
        iconPath: 'images/icons/walking_icon.png',
        text: 'Walking',
      ),
      TransportModeButton(
        iconPath: 'images/icons/bicycle_icon.png',
        text: 'Bike & eScooter',
      ),
      TransportModeButton(
        iconPath: 'images/icons/public_transport_icon.png',
        text: 'Public transport',
      )
    ],
  ),
),

Upvotes: 3

Views: 2609

Answers (4)

tareq albeesh
tareq albeesh

Reputation: 1861

you can solve it by wrapping your Row inside a BoxConstraints like:

Container(
        child: SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: ConstrainedBox(
              constraints: BoxConstraints(
                maxWidth: MediaQuery.of(context).size.width,
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                mainAxisSize: MainAxisSize.max,
                children: const [
                  Text("test1"),
                  Text("test2"),
                  Text("test3"),
                ],
              ),
            )),
      ),

Edit:

to get the constraints from the parents for your SingleChildsScrollView you can do so using LayoutBuilder, so the code would look like:

LayoutBuilder(
                builder: (BuildContext context, BoxConstraints constraints) {
              return SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: ConstrainedBox(
                    constraints: BoxConstraints(
                      maxWidth: constraints.maxWidth,
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      mainAxisSize: MainAxisSize.max,
                      children: const [
                        Text("test1"),
                        Text("test2"),
                        Text("test3"),
                      ],
                    ),
                  ));
            })

Upvotes: 8

Manishyadav
Manishyadav

Reputation: 1726

No need to use singlechildscrollview(SCSW) to counter the spacing scenario. It seems like a bad Ux for users to scroll the tile. You can let flow vertically using something like softwrap. If you still want to use SCSW then you can try to put constraints on SCSW by wrapping the child of SCSW in ConstrainedBox.

constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width)

Upvotes: 0

gorkhali1234
gorkhali1234

Reputation: 312

Row/Column takes as much space as needed, meaning it can go beyond available height if need be and if there are no constraints.

Your row is taking the needed space and not more. Hence, the MainAxisAlignment is actually working(but not how we want to). Put a SizedBox with width for a space if you want.

My advice is provided is use ListView if you know how many widgets are available and if you're not using the whole screen for this only.

Single Child Scroll View

Scaffold(
  appBar: AppBar(),
  body: SafeArea(
    child: SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: const [
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          ),
          Icon(
            Icons.nordic_walking,
            size: 50,
          ),
          SizedBox(
            width: 20,
          )
        ],
      ),
    ),
  ),
);

ListView

Scaffold(
  appBar: AppBar(),
  body: SafeArea(
    child: ListView(
      scrollDirection: Axis.horizontal,
      children: const [
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
        Icon(
          Icons.nordic_walking,
          size: 50,
        ),
        SizedBox(
          width: 20,
        ),
      ],
    ),
  ),
);

Upvotes: 0

Yahalom Software
Yahalom Software

Reputation: 724

When you wrap your Row with SCSV, there is actually no width to the row, since it is infinite.

It does not rely on the width of the screen or any other width of to calculate the space between.

If you really want to enable the space between I would suggest 2 ways:

  • To wrap the Row with a Container/SizedBox/BoxConstraints and give it a width.
  • To add SizedBox / wrap your TransportModeButton with Padding, which will create the spaces, manually, between the buttons.

Upvotes: 0

Related Questions