How to Use Cards in Flutter

Flutter App with vs without Card widget

Howdy! Today in this article I am going to show you how you can use Flutter’s card widget to organize your texts in an organized block manner.

The App

Suppose you’re writing an app similar to this one where the text doesn’t look organized:

The App without Flutter Card widget
// main.dart
import 'package:flutter/material.dart';
import 'quote.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Center(child: Text("Best Quotes")),
          backgroundColor: const Color(0xFFfb8b04),
        ),
        body: Center(child: MyCards()),
        bottomNavigationBar: BottomNavigationBar(
          items: const [
            BottomNavigationBarItem(
              label: "Home",
              icon: Icon(Icons.home),
            ),
            BottomNavigationBarItem(
              label: "Settings",
              icon: Icon(Icons.settings),
            )
          ],
          currentIndex: currentIndex,
          onTap: (int index) {
            setState(() {
              currentIndex = index;
            });
          },
        ),
      ),
    );
  }
}

class MyCards extends StatelessWidget {
  MyCards({ Key? key }) : super(key: key);

  final List<Quote> quotes = [
    Quote(author: 'Mother Teresa', text: 'Spread love everywhere you go. Let no one ever come to you without leaving happier.'),
    Quote(author: 'Nelson Mandela', text: 'The greatest glory in living lies not in never falling, but in rising every time we fall.'),
    Quote(author: 'Aristotle', text: 'It is during our darkest moments that we must focus to see the light.')
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: quotes.map((quote) => Text('${quote.text} - ${quote.author}')).toList(),
    );
  }
}
// quote.dart
class Quote {
  String? text; // errors need ?
  String? author;

  Quote({this.text, this.author});
}

You can make it look more organized by using the flutter card widget.

Widget Template And Usage

First, just below the code of my list class, I am going to make a widget class that returns a card widget with a child column and then a widget text on the column’s child argument and then pass our quote text and author (and add some styles too).

The code would look like this:

 Widget quoteTemplate(quote) {
    return Card(
      child: Column(
        children: <Widget>[
          Text(
            quote.text,
            style: TextStyle(fontSize: 18.0, color: Colors.grey[600]),
          ),
          SizedBox(height: 6.0),
          Text(
            quote.author,
            style: TextStyle(fontSize: 14.0, color: Colors.grey[800]),
          ),
        ],
      ),
    );
  }

Now to see the change I have to use the “quoteTemplate” class that I wrote to map it on the screen.

Instead of using a text widget on our map, on the build, like this:

@override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: quotes.map((quote) => Text('${quote.text} - ${quote.author}')).toList(),
    );
  }

We have to change it to this (to use our template class):

@override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: quotes.map((quote) => quoteTemplate(quote)).toList(),
    );
  }

Now that it’s on the card widget, we’re not finished yet.

Margin, Padding and Alignment

Now that my texts are on the Card widget it still doesn’t look organize and its missing something…. Margin, Padding and Alignment!

On my Card Widget I am going to add another argument called “margin” and add an EdgeInsets.fromLTRB. The function name is self-explanatory (LeftTopRightBottom) and I’m going to pass in a value of 16.0 on all sides except the bottom.

margin: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0),

Now on my Column widget, I’m also going to set the crossAxisAlignment argument to stretch.

crossAxisAlignment: CrossAxisAlignment.stretch,

And lastly, I’m going to set a padding. To do that, I have to wrap the column with the padding widget and set the padding argument value of 12 on all sides.

...
child: Padding(
        padding: const EdgeInsets.all(12.0),
...

Outcome

The App with Flutter Card widget
import 'package:flutter/material.dart';
import 'quote.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Center(child: Text("Best Quotes")),
          backgroundColor: const Color(0xFFfb8b04),
        ),
        body: Center(child: MyCards()),
        bottomNavigationBar: BottomNavigationBar(
          items: const [
            BottomNavigationBarItem(
              label: "Home",
              icon: Icon(Icons.home),
            ),
            BottomNavigationBarItem(
              label: "Settings",
              icon: Icon(Icons.settings),
            )
          ],
          currentIndex: currentIndex,
          onTap: (int index) {
            setState(() {
              currentIndex = index;
            });
          },
        ),
      ),
    );
  }
}

class MyCards extends StatelessWidget {
  MyCards({Key? key}) : super(key: key);

  final List<Quote> quotes = [
    Quote(
        author: 'Mother Teresa',
        text:
            'Spread love everywhere you go. Let no one ever come to you without leaving happier.'),
    Quote(
        author: 'Nelson Mandela',
        text:
            'The greatest glory in living lies not in never falling, but in rising every time we fall.'),
    Quote(
        author: 'Aristotle',
        text:
            'It is during our darkest moments that we must focus to see the light.')
  ];

  Widget quoteTemplate(quote) {
    return Card(
      margin: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0),
      child: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text(
              quote.text,
              style: TextStyle(fontSize: 18.0, color: Colors.grey[600]),
            ),
            SizedBox(height: 6.0),
            Text(
              quote.author,
              style: TextStyle(fontSize: 14.0, color: Colors.grey[800]),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: quotes.map((quote) => quoteTemplate(quote)).toList(),
    );
  }
}

Nicely done! Check out the code to refer to the changes with and without the card widget for reference.

Docs: https://api.flutter.dev/flutter/material/Card-class.html

Conclusion

I’ve covered how to utilize the card widget in a scenario where we have a lot of text widgets in our app to keep organized. Not only cards, but margins, padding, and alignment.

Keep following along on my Flutter journey. Until then, farewell! 

Leave a Comment

Your email address will not be published. Required fields are marked *