DEV Community

Cover image for Fast Tutorial - Beautiful credit cards with JetPack Compose
Danubius IT Solutions
Danubius IT Solutions

Posted on • Edited on • Originally published at danubius.io

Fast Tutorial - Beautiful credit cards with JetPack Compose

Shared from Danubius IT Solutions' techblog.

This fast tutorial shows how to create a list of credit cards with JetPack Compose. Just follow the steps and try out Google’s declarative UI framework today!

Prerequisites

  • Latest version of Android Studio
  • JDK 11 or higher
  • Physical or virtual device for testing

Anatomy

Card example

The idea is very simple: Create a card, add a mesh gradient image, put over a box layout and take the parts to the right places. The key is the Box layout. With this composable, you can put elements in the 4 corners of the box. See the reference docs for more about Box layout.

Prepare

First of all, create a new Android Project and select Empty Compose Activity. Then clean up the sample code.

Get the image and font resources:

  • Visa logo
  • MasterCard logo
  • Space Mono font
  • Space Grotesk font
  • Some mesh gradients

Put image resources to /res/drawable.

Create a new resource folder for fonts: /res/font and copy font files (Space Grotesk bold for cardholder name and Space mono regular for card number).

Create CreditCard() composable

Create a new Kotlin file under the ui package and name it CreditCard.kt. Start a new composable function and add empty Card() component:

@Composable
fun CreditCard() {
Card(
modifier = Modifier
.height(200.dp),
shape = RoundedCornerShape(8.dp),
elevation = 8.dp
) { }
}

Add Image() inside card content for the mesh background:

@Composable
fun CreditCard(cardInfo: CardInfo) {
Card(
modifier = Modifier
.height(200.dp),
shape = RoundedCornerShape(8.dp),
elevation = 8.dp
) {
Image(
painter = painterResource(id = R.drawable.card_mesh),
contentDescription = "Card Background",
contentScale = ContentScale.FillBounds
)
}
}

The FillBounds content scale will expand the image to match the size of the card.

After the image, put a new Box() layout with some padding:

Box(modifier = Modifier.padding(16.dp)) { }
Add Image() to the Box TopStart position and load the Visa logo.
Box(modifier = Modifier.padding(16.dp)) {
Image(
painter = painterResource(id = R.drawable.visa),
contentDescription = "Visa",
modifier = Modifier
.width(86.dp)
.align(Alignment.TopStart)
)
}

Prepare the font faces to use for card number and cardholder texts. Open ui/theme/Type.kt and create new font families:

val SpaceMono = FontFamily(
Font(R.font.space_mono_regular)
)
val SpaceGrotesk = FontFamily(
Font(R.font.space_grotesk_bold, FontWeight.Bold)
)

Now you can use them in other composables.

To align the card number and the cardholder name under each other, we will use a Column() wrapper component and put the Text() inside it.

Box(modifier = Modifier.padding(16.dp)) {
Image(
painter = painterResource(id = R.drawable.visa),
contentDescription = "Visa",
modifier = Modifier
.width(86.dp)
.align(Alignment.TopStart)
)
Column(modifier = Modifier
.align(Alignment.BottomStart)) {
Text(
text = "5435 9876 1234 6543",
fontFamily = SpaceMono,
letterSpacing = 1.2.sp,
fontSize = 16.sp
)
Text(
text = cardInfo.cardHolder,
fontFamily = SpaceGrotesk,
letterSpacing = 1.1.sp,
fontSize = 16.sp
)
}
}

Showtime

The CreditCard() composable is ready to use, put inside your app component:

@Composable
fun DiCardApp() {
DanubiusCreditCardTheme {
Column(
modifier = Modifier
.fillMaxHeight()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
CreditCard(cardInfo = CardInfo(
backgroundDrawable = R.drawable.card_mesh,
providerDrawable = R.drawable.mc,
cardNumber = "8547 9658 6325 4521",
cardHolder = "John Fluffy"
))
}
}
}

More than one

Create a new data class to hold the attributes of a CreditCard() composable, for example CardInfo.kt.

data class CardInfo(
val cardNumber: String,
val cardHolder: String,
val providerDrawable: Int,
val backgroundDrawable: Int
)

Create a fake list of cards:

val cards = listOf(
CardInfo(
backgroundDrawable = R.drawable.card_mesh,
providerDrawable = R.drawable.mc,
cardNumber = "8547 9658 6325 4521",
cardHolder = "Jim Hopper"
),
CardInfo(
backgroundDrawable = R.drawable.card_mesh_2,
providerDrawable = R.drawable.visa,
cardNumber = "6582 4521 3256 8522",
cardHolder = "Steve Harrington"
),
CardInfo(
backgroundDrawable = R.drawable.card_mesh_3,
providerDrawable = R.drawable.visa,
cardNumber = "9856 7452 2569 7413",
cardHolder = "Joyce Byers"
)
)

Change Column() component to LazyColumn() and load the items of cards list.

LazyColumn(
modifier = Modifier
.fillMaxHeight()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(cards) { card ->
CreditCard(cardInfo = card)
}
}

Refactor the CardInfo component to display CardInfo object attributes. See the final implementation below:

@Composable
fun CreditCard(cardInfo: CardInfo) {
Card(
modifier = Modifier
.height(200.dp),
shape = RoundedCornerShape(8.dp),
elevation = 8.dp
) {
Image(
painter = painterResource(id = cardInfo.backgroundDrawable),
contentDescription = "Card Background",
contentScale = ContentScale.FillBounds
)
Box(modifier = Modifier.padding(16.dp)) {
Image(
painter = painterResource(id = cardInfo.providerDrawable),
contentDescription = "Visa",
modifier = Modifier
.width(86.dp)
.align(Alignment.TopStart)
)
Column(modifier = Modifier.align(Alignment.BottomStart)) {
Text(
text = cardInfo.cardNumber,
fontFamily = SpaceMono,
letterSpacing = 1.2.sp,
fontSize = 16.sp
)
Text(
text = cardInfo.cardHolder,
fontFamily = SpaceGrotesk,
letterSpacing = 1.1.sp,
fontSize = 16.sp
)
}
}
}
}

That’s it! You can play around with other backgrounds, fonts, and layouts. You can find the full example on GitHub in this repository. Don’t forget to ⭐️ the repository.

Final results

Top comments (0)