【问题标题】:Flutter - Non-scrollable GridFlutter - 不可滚动的网格
【发布时间】:2020-02-03 12:10:09
【问题描述】:

有没有办法构建一个本身不可滚动且大小取决于其子级的网格,就像我们可以在行或列中指定 mainAxisSize: MainAxisSize.min 一样?

为您提供全局 -

我正在尝试创建一个取决于设备宽度的响应式布局。 它应该分成两部分,通过列无缝连接。

1) 2 个大小取决于屏幕宽度的大容器,考虑到它们之间的小空间。每个容器的宽度和高度都相同(方形容器)。

2) 相同的想法,但有 3 行,每行包含 3 个较小的容器。 这将创建一个网格。尽管网格本身不能滚动并且其大小将取决于其子级,但这一点非常重要。它只能与 SingleChildScrollView 中包含的页面的其余部分一起滚动。

特别是因为每个容器的高度都需要与其宽度相同,我正在考虑使用行、列和 LayoutBuilder 的组合 - 它们为我提供了我需要的所有功能。

但是,在手动执行操作之前,我想知道是否有一些开箱即用的方法。

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    这样的?

    SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Row(
            children: <Widget>[
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: AspectRatio(
                    aspectRatio: 1.0,
                    child: Container(
                      width: double.infinity,
                      decoration: BoxDecoration(
                        border: Border.all(width: 3.0, color: Colors.green),
                      ),
                    ),
                  ),
                ),
              ),
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: AspectRatio(
                    aspectRatio: 1.0,
                    child: Container(
                      width: double.infinity,
                      decoration: BoxDecoration(
                        border: Border.all(width: 3.0, color: Colors.green),
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
          Container(
            padding: const EdgeInsets.all(10.0),
            child: GridView.builder(
              physics: NeverScrollableScrollPhysics(),
              shrinkWrap: true,
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                childAspectRatio: 1.0,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
              ),
              itemCount: 21,
              itemBuilder: (context, index) {
                return Container(
                  decoration: BoxDecoration(
                    border: Border.all(width: 3.0),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    )
    

    【讨论】:

    • 非常感谢你。我花了将近 10 个小时来做​​这个......再次感谢伙计。
    • @Emon 我花了 6 个小时试图解决这个问题,哈哈
    • "......失去了将近 10 个小时","......花了 6 个小时......" smh,我喜欢编程
    【解决方案2】:

    table widget 可能是比 GridView(janstol 的答案)更简单的方法,因为它是专为您正在寻找的东西而构建的。尽管这不适用于您的情况,但如果您的小部件可以具有不同的大小,Table 将特别有用 - 它会相对于每列/行中最宽/最高的小部件(分别)垂直和水平对齐小部件。

    这里是 janstol 的解决方案代码重写为使用表。请注意,Table 要求所有行的长度相同,因此您的前两个元素行需要位于表之外。

    Widget bigBox = Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: AspectRatio(
                    aspectRatio: 1.0,
                    child: Container(
                      width: double.infinity,
                      decoration: BoxDecoration(
                        border: Border.all(width: 3.0, color: Colors.green),
                      ),
                    ),
                  ),
                ),
              );
              Widget smallBox = Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: AspectRatio(
                    aspectRatio: 1.0,
                    child: Container(
                      width: double.infinity,
                      decoration: BoxDecoration(
                        border: Border.all(width: 3.0),
                      ),
                    ),
                  ),
                );
              return Scaffold(
                body: SingleChildScrollView(
                  child: Column(
                    children: [
                      Row(
                        children: List.filled(2, bigBox),
                      ),
                      Container(
                        child: Table(
                          children: List.filled(
                              // 7 rows instead of 3 just to demonstrate the scrolling functionality
                              7,
                              TableRow(
                                children: List.filled(3, smallBox),
                              )
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
    

    【讨论】:

    • 欢迎提供指向解决方案的链接,但请确保您的答案在没有它的情况下有用:在链接周围添加上下文,以便您的其他用户了解它是什么以及为什么存在它,然后引用在目标页面不可用的情况下,您链接到的页面的最相关部分。
    • 感谢 Zahra 的反馈,我已经完全重写了我的答案,使其更加彻底,并且无需链接即可独立使用。
    【解决方案3】:

    您可以为其创建一个自定义小部件,这是code,用于从google ui 包中创建一个不可滚动的网格小部件。

    import 'package:flutter/material.dart';
    
    /// Create a grid.
    class GoogleGrid extends StatelessWidget {
      const GoogleGrid({
        Key? key,
        this.columnCount = 2,
        this.gap,
        this.padding,
        required this.children,
      }) : super(key: key);
    
      /// Number of column.
      final int columnCount;
    
      /// Gap to separate each cell.
      final double? gap;
    
      /// An empty space.
      final EdgeInsets? padding;
    
      /// The widgets below this widget in the tree.
      final List<Widget> children;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          padding: padding,
          child: Column(children: _createRows()),
        );
      }
    
      List<Widget> _createRows() {
        final List<Widget> rows = [];
        final childrenLength = children.length;
        final rowCount = (childrenLength / columnCount).ceil();
    
        for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
          final List<Widget> columns = _createRowCells(rowIndex);
          rows.add(Row(children: columns));
          if (rowIndex != rowCount - 1) rows.add(SizedBox(height: gap));
        }
    
        return rows;
      }
    
      List<Widget> _createRowCells(int rowIndex) {
        final List<Widget> columns = [];
        final childrenLength = children.length;
    
        for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
          final cellIndex = rowIndex * columnCount + columnIndex;
          if (cellIndex <= childrenLength - 1) {
            columns.add(Expanded(child: children[cellIndex]));
          } else {
            columns.add(Expanded(child: Container()));
          }
    
          if (columnIndex != columnCount - 1) columns.add(SizedBox(width: gap));
        }
    
        return columns;
      }
    }
    

    使用方法与使用列或行小部件相同,您可以定义列数、间隙、填充和边距。

    GoogleGrid(
      gap: 16,
      padding: const EdgeInsets.all(16),
      children: [
        Text("1"),
        Text("2"),
        Text("3"),
        Text("4"),
        Text("5"),
        Text("6"),
      ],
    );
    

    【讨论】:

      猜你喜欢
      • 2021-01-10
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 2020-11-05
      相关资源
      最近更新 更多