Search code examples
flutterheighttile

Inconsistent height of Card widget in Flutter with ListTile as child


When I am using Card and ListTile as its child, the height of cards differs based on the number of text lines of the subtitle parameter of ListTile. If title and subtitle are single lines of text there's some sort of top and bottom padding (highlighted with green rectangles). However, if subtitle consists of several lines of text, there's no top and bottom padding and the height of the card is smaller. What causes this inconsistency? How can I remove this padding from cards 1 and 2 or add it to card 3?

class CardList extends StatelessWidget {
  List<List<String>> cardList = [
    ["Apple", "Fruit"],
    ["Book", "Thing"],
    [
      "Lorem ipsum",
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vulputate tortor non mi gravida, nec"
    ]
  ];

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: cardList.length,
        itemBuilder: (BuildContext context, int position) {
          return Card(
              elevation: 2.0,
              child: ListTile(
                title: Text(cardList[position][0]),
                subtitle: Text(cardList[position][1]),
              ));
        });
  }
}

screenshot of the problem


Solution

  • This is how ListTile works out of the box, you could check the source code if you want, but don't worry, this is Flutter, you can create and customize your own widget very easily.

    class MyListTile extends StatelessWidget {
      final String title;
      final String subtitle;
    
      const MyListTile({Key key, this.title, this.subtitle}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final textTheme = Theme.of(context).textTheme;
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                title,
                style: textTheme.subhead,
              ),
              subtitle != null
                  ? Text(
                      subtitle,
                      style: textTheme.body1,
                    )
                  : const SizedBox.shrink()
            ],
          ),
        );
      }
    }
    

    Usage

      @override
      Widget build(BuildContext context) {
        return ListView.builder(
            itemCount: cardList.length,
            itemBuilder: (BuildContext context, int position) {
              return Card(
                elevation: 2.0,
                child: MyListTile(
                  title: cardList[position][0],
                  subtitle: cardList[position][1],
                ),
              );
            });
      }
    

    Result

    enter image description here