Home > Software design >  Flutter wrapping Row in SingleChildScrollview ruins spaceBetween
Flutter wrapping Row in SingleChildScrollview ruins spaceBetween

Time:03-09

I have a Row 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',
                    )
                  ],
                ),
              ),

CodePudding user response:

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"),
                      ],
                    ),
                  ));
            })

CodePudding user response:

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.

CodePudding user response:

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,
        ),
      ],
    ),
  ),
);

CodePudding user response:

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)

  • Related