SingleChildScrollview 中的 Flutter 包装行破坏了 spaceBetween

Flutter wrapping Row in SingleChildScrollview ruins spaceBetween

我有一个 Row 个按钮,它们的父级为 SingleChildScrollView,水平。 包裹 SingleChildScrollView 后,行的元素不遵守 mainAxisAlignment,特别是 space 之间,它们与不 space 之间...

如何使 spaceBetween 再次工作?

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

您可以通过将 Row 包裹在 BoxConstraints 中来解决它,例如:

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

编辑:

要从 parents 中为您的 SingleChildsScrollView 获取约束,您可以使用 LayoutBuilder 来实现,因此代码如下所示:

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

当您用 SCSV 包裹行时,行实际上没有宽度,因为它是无限的。

它不依赖于屏幕的宽度或任何其他宽度来计算space之间。

如果你真的想启用space,我会建议两种方式:

  • 用 Container/SizedBox/BoxConstraints 包裹行并给它一个宽度。
  • 要添加 SizedBox/用 Padding 包装您的 TransportModeButton,这将在按钮之间手动创建 spaces。

Row/Column 根据需要占用 space,这意味着如果需要且没有限制,它可以超出可用高度。

您的行占用了所需的 space,而不是更多。因此,MainAxisAlignment 实际上在工作(但不是我们想要的方式)。如果需要,请放置一个宽度为 space 的 SizedBox。

我的建议是,如果您知道有多少小部件可用并且您不只是为此使用整个屏幕,请使用 ListView。

单子滚动视图

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

列表视图

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

无需使用singlechildscrollview(SCSW) 来应对间隔场景。用户滚动磁贴似乎是一个糟糕的用户体验。您可以使用 softwrap 之类的东西让垂直流动。如果您仍想使用 SCSW,那么您可以尝试通过将 SCSW 的子项包装在 ConstrainedBox.

中来对 SCSW 施加约束

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