dMovie App with Flutter: Part 1 -Creating a card widget

Balaji ramasamy
3 min readMar 1, 2021
Image with width as 185

Step 1: Create a stateless widget.

class ContentCard extends StatelessWidget {  const ContentCard({Key key}) : super(key: key);  @override
Widget build(BuildContext context) => Container();
}

Step 2: Add required parameters.

We need an image URL, title, subtitle and badge. We can mark image URL and title as minimum required parameters. Subtitle and badge are optional. Add assert statements to ensure required parameters are passed.

class ContentCard extends StatelessWidget {
final String image;
final String title;
final String subtitle;
final String badge;
const ContentCard({
@required this.image,
@required this.title,
this.subtitle,
this.badge,
Key key,
}) : assert(image != null, 'image url is required'),
assert(title != null, 'title is required'),
super(key: key);
// ...}

Step 3: Add a Column widget.

Column widget will take a list of widgets as children and shows them one by one. Column widget will align its children in center by default. We can override this to show left aligned by passing the crossAxisAlignment argument as CrossAxisAlignment.start.

class ContentCard extends StatelessWidget {
// ...
@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[],
);
}

Step 4: Add Image :

First child of the Column widget will be an Image.

Let’s use FadeInImage.memoryNetwork. This widget let’s us show placeholder image from memory while loading the actual image from network. Let’s give the fit as BoxFit.cover, so our image’s aspect ratio will be preserved to an extend while trying to fill the available space.

FadeInImage.memoryNetwork(
image: image,
placeholder: kTransparentImage,
fit: BoxFit.cover,
),

For place holder image we can use the kTransparentImage from transparent_image dependency. Add the below dependency in the pubspecl.yml.

transparent_image: ^1.0.0

Our design requires image to have rounded corners. So let’s wrap our image widget with a ClipRRect widget. We can give a circular border radius of 16 to ClipRRect.

ClipRRect(
borderRadius: BorderRadius.circular(16),
child: FadeInImage.memoryNetwork(
// ..
),
)

Step 5: Add a SizedBox

Let’s add a sized box with height as 8 to give a space between our image and title.

const SizedBox(height: Sizes.dimen_10),

Step 7: Get the TextTheme

To style our Text widgets we need an instance of our TextTheme from ThemeData. We can the instance of ThemeData from global context using Theme.of(context) method. assign the textTheme to a final variable so we don’t have to call Theme.of(context) method multiple times.

Widget build(BuildContext context) {
final TextTheme textTheme = Theme.of(context).textTheme;
// ....
}

Step 6: Add title text:

Add a Text widget. data will be the title. Overflow will be TextOverflow.ellipsis so our text will show like “Mortal Kombat …”.

Text(
title,
overflow: TextOverflow.ellipsis,
style: textTheme.headline6,
),

Step 7: Add subtitle text:

Add a Text widget in same way as title Text except the style will be textTheme.subtitle2. Since subtitle is an optional parameter, add null check before the widget.

if (subtitle != null)
Text(
subtitle,
overflow: TextOverflow.ellipsis,
style: textTheme.subtitle2,
),

Step 8: Adding a badge

The rating badge is a rectangular box with rounded corner and a text in the middle.

We can use a container with Padding, BoxDecoration and child as Text to achieve this.

Since badge is optional add a null check. The text theme will have the following ararguments , overflow is TextOverflow.ellipsis and style is textTheme.bodyText1.

if (badge != null)
Container(
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(5)),
),
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
child: Text(
badge ?? '',
overflow: TextOverflow.ellipsis,
style: textTheme.bodyText1,
),
),

Whole code:

The design depends on the image size. We can provide image with different sizes like

image with width as 500
image with width as 342

In the next post let’s use this card in a list view to see the list of contents.

This is my first attempt at writing blog post. Please let me know your thought in the comments. Thanks.

--

--