如何布置各种高度的卡片列表?

时间:2018-05-24 23:27:45

标签: flutter

我刚刚开始使用Flutter。

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

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

例如,这是我绘制的模型,我正在努力完成。

enter image description here

Flutter不喜欢ListView内的Card。它会产生以下错误:

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小部件上设置它?
  3. 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,
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                )
              ],
            ),
          ),
        );
      }
    }
    

1 个答案:

答案 0 :(得分:4)

CardModel:表示每个列表项,其中包含可选的标头和字符串列表。构建ListView:如果头字段是persent,它将添加到列中,那么该卡的字符串列表也会添加到上面的列中。最后,这些单独创建的卡片将作为列表包装并显示在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"]),
];