首页 > 解决方案 > 在 Flutter 中制作 2x2 网格

问题描述

我正在尝试创建一个 2x2 网格以在卡片中显示一些信息。免责声明:我对 Dart 和 Flutter 完全陌生,所以在这里期待很多关于这个话题的无知。

这些卡片应该有一个固定的尺寸,有一张图片,显示一些文字......并且从左到右,从上到下放置。

首先,我尝试使用 Flex 小部件,但它似乎只能水平或垂直工作。因此,我唯一的解决方案是使用两个 Flex,但仅在元素数量高于 2 时显示第二个(仅使用一行)。

然后,我尝试使用 GridView,但它无法以任何可能的方式工作。我复制并粘贴 Internet 上的哪个示例开始测试并不重要:它们不会出现在屏幕上,除非它们是应用程序中唯一显示的东西,没有任何其他小部件。我仍然不明白为什么会这样。

这是我当前的代码:

“home_page.dart”中的第一个小部件:

return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Padding(padding: EdgeInsets.only(top: 30)),
            Text(
              'App test',
              style: TextStyle(fontSize: 24),
            ),
            EventsList(key: new Key('test')),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );

“EventList”部分是一个小部件,应该代表我之前解释过的网格功能。此类从服务中获取一些信息(当前只是从 Future 发送一些硬编码信息),并将给定的小部件(基本上是“卡片”项目)绘制到 EventList 视图中:

class _EventsListState extends State<EventsList> {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Event>>(
        future: new EventsService().getEventsForCoords(),
        builder: (context, AsyncSnapshot<List<Event>> snapshot) {
          if (snapshot.hasData) {
            return Padding(
                padding: EdgeInsets.only(left: 20, right: 20),
                child: Flex(
                  direction: Axis.horizontal,
                  verticalDirection: VerticalDirection.down,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: generateProximityEventCards(snapshot.data),
                ));
          } else {
            return CircularProgressIndicator();
          }
        });
  }

  List<Card> generateProximityEventCards(List<Event> eventList) {
    // Load Events from API
    print(eventList);

    // Render each card
    return eventList.map((Event ev) {
      return Card(
          child: Padding(
        padding: EdgeInsets.only(bottom: 15),
        child: Column(
          children: <Widget>[
            Image(
              fit: BoxFit.cover,
              image: ev.imageUrl,
              height: 100,
              width: 150,
            ),
            Padding(
              child: Text(ev.name),
              padding: EdgeInsets.only(left: 10, right: 10),
            ),
            Padding(
              child: Text(ev.address),
              padding: EdgeInsets.only(left: 10, right: 10),
            ),
          ],
        ),
      ));
    }).toList();
  }
}

这是它目前的样子:

正如我之前所说,我知道 Flex 小部件无法真正获得我正在寻找的 2x2 网格外观,这将是这样的(使用 Paint 完成):

所以,一些问题:

  1. 我怎样才能让这样的网格工作?请记住,我希望在其下方有更多东西,因此它不能是“无限”网格,也不能是完整的窗口网格。
  2. 是否可以在该网格的容器中向右滚动?因此,如果有超过 4 个元素,我只需用手指向右滚动即可到达其他元素。
  3. 正如您在第一张图片中看到的那样,第二个示例比第一个大。如何限制卡的大小?

非常感谢您的帮助!

标签: flutterdart

解决方案


gridview 不工作的原因是您需要将gridView 的shrinkWrap 属性设置为true,以使其占用尽可能少的空间。(默认情况下,gridview 和 listview 等可滚动小部件会占用尽可能多的垂直空间,如果将其放在列小部件中,则会出现错误)

尝试使用这样的可滚动GridView.count小部件并将 shrinkWrap 设置为 true:

...

GridView.count(
  primary: false,
  padding: /* You can add padding: */ You can add padding const EdgeInsets.all(20),
  crossAxisCount: /* This makes it 2x2: */ 2,
  shrinkWrap: true,
  children: generateProximityEventCards(snapshot.data),

...

推荐阅读