【问题标题】:How to layout a list of cards with various height?如何布局不同高度的卡片列表?
【发布时间】:2018-11-04 06:45:55
【问题描述】:

我刚刚开始使用 Flutter。

在屏幕上布置卡片列表的推荐方式是什么?

有些卡片只包含一个对象作为一行文本,但其他卡片包含多个对象作为文本行也应该在卡片内有一个标题。

例如,这是我画的一个模型,我正在努力完成。

Flutter 不喜欢 ListViewCard 中。它会产生以下错误:

I/flutter (13243): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (13243): The following assertion was thrown during performResize():
I/flutter (13243): Vertical viewport was given unbounded height.
I/flutter (13243): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (13243): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (13243): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (13243): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (13243): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (13243): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (13243): the height of the viewport to the sum of the heights of its children.

在@aziza 的帮助下,我敲定了以下代码,并提供了一个与我模拟的非常接近的基本布局,但我有几个问题:

  1. 这是最有效地使用嵌套小部件吗?
  2. 有没有办法设置全局字体大小,这样我就不必在每个 Text 小部件上都设置它了?

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My Layout',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'App Bar Title'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List itemList = [
    'Card Text 2 Line 1',
    'Card Text 2 Line 2',
    'Card Text 2 Line 3',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Sub Title',
                    style: TextStyle(
                      fontSize: 25.0,
                    ),
                  ),
                ],
              ),
            ),
            Row(
              children: [
                Expanded(
                  child: Card(
                    shape: RoundedRectangleBorder(
                      side: BorderSide(
                        width: 3.0,
                      ),
                    ),
                    margin: EdgeInsets.all(15.0),
                    color: Colors.grey,
                    elevation: 10.0,
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(
                        'Card 1 Text',
                        style: TextStyle(
                          fontSize: 25.0,
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
            Row(
              children: [
                Expanded(
                  child: Card(
                    shape: RoundedRectangleBorder(
                      side: BorderSide(
                        width: 3.0,
                      ),
                    ),
                    margin: EdgeInsets.all(15.0),
                    color: Colors.grey,
                    elevation: 10.0,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Text(
                                'Card 2 Header',
                                style: TextStyle(
                                  fontSize: 25.0,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: List.generate(
                            itemList.length,
                            (i) => Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: Text(
                                    itemList[i],
                                    style: TextStyle(
                                      fontSize: 25.0,
                                    ),
                                  ),
                                ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
            Row(
              children: [
                Expanded(
                  child: Card(
                    shape: RoundedRectangleBorder(
                      side: BorderSide(
                        width: 3.0,
                      ),
                    ),
                    margin: EdgeInsets.all(15.0),
                    color: Colors.grey,
                    elevation: 10.0,
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(
                        'Card 3 Text',
                        style: TextStyle(
                          fontSize: 25.0,
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

  • “Flutter 不喜欢 Card 中的 ListView”是什么意思?
  • @aziza,我添加了将 ListView 放入卡片中产生的错误。
  • 什么布局产生了这个错误,这是一个简单的约束问题,如果你添加产生错误的代码人们很容易解决它
  • 我想我明白了,在您的多行卡片中,您为什么要使用 ListView ?我认为您的意思是使用 Column 代替
  • @aziza,每张卡片的行数不是固定的。它可以改变。列可以处理一组可变的行吗?

标签: flutter


【解决方案1】:

CardModel:表示每个列表项,其中包含可选的标题和字符串列表。构建ListView:如果header字段被添加到一个列中,那么卡片的字符串列表也被添加到上面的列中。最后,这些单独创建的卡片被包装为一个列表并显示在 ListView 中。

import 'package:flutter/material.dart';

void main() => runApp(
      new MaterialApp(
        debugShowCheckedModeBanner: false,
        home: new CardsDemo(),
      ),
    );

class CardsDemo extends StatefulWidget {
  @override
  _CardsDemoState createState() => new _CardsDemoState();
}

class _CardsDemoState extends State<CardsDemo> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Cards'),
      ),
      body: new Column(
        children: <Widget>[
          new Center(
            child: new Padding(
              padding: const EdgeInsets.all(15.0),
              child: new Text(
                'Sub Title',
                style:
                    new TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          new Expanded(
            child: new ListView(
              children: _buildCards(),
              padding: const EdgeInsets.all(8.0),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildCard(CardModel card) {
    List<Widget> columnData = <Widget>[];

    if (card.isHeaderAvailable) {
      columnData.add(
        new Padding(
          padding: const EdgeInsets.only(bottom: 8.0, left: 8.0, right: 8.0),
          child: new Text(
            card.headerText,
            style: new TextStyle(fontSize: 24.0, fontWeight: FontWeight.w500),
          ),
        ),
      );
    }

    for (int i = 0; i < card.allText.length; i++)
      columnData.add(
        new Text(card.allText[i], style: new TextStyle(fontSize: 22.0),),
      );

    return new Card(
      child: new Padding(
        padding: const EdgeInsets.symmetric(vertical: 15.0),
        child: Column(children: columnData),
      ),
    );
  }

  List<Widget> _buildCards() {
    List<Widget> cards = [];
    for (int i = 0; i < sampleCards.length; i++) {
      cards.add(_buildCard(sampleCards[i]));
    }

    return cards;
  }
}

class CardModel {
  final String headerText;
  final List<String> allText;
  final bool isHeaderAvailable;

  CardModel(
      {this.headerText = "", this.allText, this.isHeaderAvailable = false});
}

List<CardModel> sampleCards = [
  new CardModel(allText: ["Card 1 Text"]),
  new CardModel(
      isHeaderAvailable: true,
      headerText: "Card 2 Header",
      allText: ["Card 2 Text Line 1", "Card 2 Text Line 2"]),
  new CardModel(allText: ["Card 3 Text"]),
];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-13
    • 2017-06-27
    • 2016-06-22
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 2020-10-03
    • 2017-11-11
    相关资源
    最近更新 更多