Jetpack Compose Part 2 How to create Card layout

Jetpack Compose for Android, it sounds good! In this second part we will be actually getting our hands dirty as we will create the Profile Card layout similar to the CardView in Android using only Jetpack composable functions.

Article series breakdown and progress:

As in this second part we will not focus on the actual state of the profile card, we want to end up with this composable layout design:

Let’s code!!

This second part will require changes on the project we started on the first part, but if you haven’t followed up or if you want a clean slate, download the starting point for this article from this link.

Alright, since part 1 of these series we are a bit familiar with how our code will be structured: lots of Compose functions. Let’s take the manner into our own hands and start from scratch by deleting those composable functions in our previously created MainActivity (in the starting point project provided above I have already deleted them for you).

Now, let’s create a new composable function for our activity: MainActivityComposable() and let’s add the @Composable annotation to it. Our MainActivity should now look like this:

As it would make sense, we are going to work on the MainActivityComposable() function, and hence we passed it to the setContent, we should also pass it to our preview composable function UserProfileCardPreview so we can preview what we are working on.

Alright! Let’s first add a Surface composable function inside the MainActivityComposable in order to get the murky green background of our Activity.

Remember: Surface is a component provided by the Compose library, just like Text or Button is. You can think of the Surface composable as a container view.

First off, we tell Compose through the modifier parameter that the surface should fill the whole screen by specifying fillMaxSize as well as the colour through the color parameter. (You can get the helper class either from here or search it inside the solution of this part). You can think of the modifier parameter as handle to specifying different customization options.

As you can see in the above gist, we have passed to our Surface another composable function called ProfileCardComposable which will actually feature our profile card widget:

Our profile card is actually a Row composable that is composed by another 2 composables: ProfilePictureComposable and ProfileContentComposable which for now will be empty. While these 2 functions will hold the actual content, let’s focus on the Row composable for now which is actually another pre-defined composable from Jetpack. Similar to Row we have Column:

This image has an empty alt attribute; its file name is Screenshot-2020-09-27-at-12.04.25.png

This looks familiar doesn’t it? Basically columns and rows work like the views within the classic LinearLayout with vertical or horizontal orientation. For our profile card container, a simple Row is the way to go here. Since our Row will contain 2 composable functions (ProfilePictureComposable and ProfileContentComposable), their content will be laid out vertically.

Alright, we want to create a view that resembles to a card, so let’s customize the row by first setting the modifier to wrap content, just like we used to do on the old View:

We then chain a clipping modifier to get the rounded corners effect by passing another widget provided by Compose called RoundedCornerShape(). We also set the background to white with the background modifier.

Finally, we add padding to our card with the padding modifier so that any upcoming text elements will have some breathing space inside the container. Similar to our classic old View, right?


! When adding modifiers to the Modifier parameter, the order matters because modifiers are applied in sequential order. For example, in our case we need to apply the background before applying the padding in order to get the desired results.


While refreshing the preview, we can see that card doesn’t look like we would really it to. It’s still missing the picture, the name and the activity text that denotes the online status of the user:

Let’s work on the profile picture composable first by editing the ProfilePictureComposable function and adding an Image composable inside. Image is a Compose function that comes out of the box with Compose and is similar to our old ImageView.

For it to render we add a source and scale via the painterResource and contentScale parameters. We also specify the size through the modifier Modifier.size and the content description with contentDescription.

Hmm but we are still missing the round aspect of the drawable we’ve set, so let’s also wrap the Image composable inside another Compose function called Card like this:

As parameters, we specify a CircleShape for the card’s shape, as well as border, size and elevation. All of these parameters we’ve passed are composables provided by Compose out of the box. Finally, our profile card starts looking nice:

Don’t worry about that weird way of getting the color, it’s just a helper method, get the gist here. For instance, you might as well pass it like this: color = colorResource(id = R.color.yourColor)

Time to work on the name and the activity text of our profile card, the last piece to the puzzle! Let’s navigate to our empty ProfileContentComposable function and add a Column as the parent composable since we want the name of the user and the activity text to be positioned vertically inside the column:

We’ve added 2 Text composables that hold harcoded values for now. We will make the card content dynamic in the final part of this article series. Let’s see how our preview renders:

Much better! But we are still missing some things. We could use some padding and also some styling and positioning. First, we are making the the name of the user profile bold with the fontWeight parameter passed to the first Text composable.

Also, let’s gray out the activity text by passing the style parameter to the second Text as typography.body2. Don’t worry, all of these are provided out of the box by Compose.

Lastly, let’s add some padding to the column by specifying the start padding with the Modifier parameter as well some vertical arrangement for the inner content:

For the arrangement, we wanted the children (the two Text elements) to be positioned centrally on the vertical axis so we first added a vertical arrangement as Alignment.CenterVertically. Secondly, we wanted to make sure that the Column fills the entire height to match the height of the profile picture through fillMaxHeight.

The result is quite different than expected though:

The problem is that we told the Column to take all available height from its parent which was the Row within ProfileCardComposable. We hoped that the fillMaxHeight modifier would make our Column occupy as much height as the ProfilePictureComposable.

Oh boy we were wrong! And that’s because the ProfileCardComposable has no specified height, so it also takes as much space as it needs. In order to fix this mess, let’s make some changes to the ProfileCardComposable:

We first replaced the root Row with a Card and then nested another Row inside the card that would hold our ProfilePictureComposable and our ProfileContentComposable.

Finally, while the card has the freedom to wrap its content size, we specified that the newly created Row should max out its intrinsec height through the height(intrinsecSize = IntrinsecSize.Max) modifier. This basically means that we are matching the height of the Row to the minimum height of the tallest element.

Finally, our code should look like this:

Let’s check out the final result and see if it matches out with what we have set out in the beginning of this article:

Perfect, we’ve done it! I know it might seem a lot of code, but in long term due to its re-usability all the effort will be worth the while.

To make sure you followed correctly (or if maybe you got stuck at some point) check out the final code for this part at this gist here.

Alright, we’ve created the layout but our composable card doesn’t have different states for an online/offline user. We will cover this in the upcoming tutorial, check it out here.


I want you focused for the third and last part so take a break and see ya in the next article! And remember, if you enjoyed this article, subscribe or maybe even gift me a coffee using the coffee bottom widget! I am already an addict!

3+

2 thoughts on “Jetpack Compose Part 2 How to create Card layout

Comments are closed.

%d bloggers like this: