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:
- Jetpack Compose Part 1: How to compose UI
- Jetpack Compose Part 2: How to create Card layout ⬅
- Jetpack Compose Part 3: Adding state
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 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!
2 thoughts on “Jetpack Compose Part 2 How to create Card layout”
Comments are closed.