Jetpack Compose is the new future UI toolkit to develop views in Android development. In this article, we’ll see how to create a custom view who reacts depending on a condition from the model object in input. If you don’t know Jetpack Compose at all, I advise you to read the official documentation first on Android documentation website.
Disclaimer: All source code exposed here has been developed with artifact 0.1.0-dev14 of Compose. Because Jetpack Compose is still in an early developer preview, note that some source code may change with new versions.
At Decathlon, each product has a price and a strict design specification.
- if your price is not on special offer, the background is yellow, the text is black, the currency is at the end of the price and there is a padding between the text and the background.
- If your price is on special offer, the background switch in red, the text in white and a banner is displayed at the top of the price block with the strikeout price and the percentage applied.
We can already see the condition that will react depending on whether the price has a promotion or not. A model that meets these specifications might look like this:
Write our first composable function
Price block composable function displays the product price. To write a composable, you need to declare a function that starts with an uppercase letter by convention and annotated by @Composable annotation.
This function displays nothing for now. Price block is pretty simple, we want to draw a background in yellow and the price on top of it. To do so, we use 3 composable functions provided by Compose library:
- Surface: To draw our yellow background
- Box: To encapsulate our text to add a padding between the background and the text
- Text: To display a text with our price and currency
Note that we are using Decathlon’s colors for the red, yellow, black and white. Create a Kotlin files with these colors:
We can use these colors everywhere in our module with a simple import. Now, we can create the yellow background of our composable:
There are a lot of parameters available for Surface composable (like elevation, shape, borders, etc.). For now we don’t need these parameters to build our composable, it will be the topic of another article.
To add a padding between our background and our text, we add a Box with a Modifier. A Modifier isn’t a composable but it can be used inside a lot of them with the parameter modify, and are used to modifier how the component is drawn.
We could do a lot more with Modifier but in our case, we’ll focus on a Surface containing a Box, a padding and a simple Text.
Finally, we declare our Text that shows our price with a specific style. To do so, we customize color, fontWeight, fontSize and fontFamily properties.
You’re done! You’ve just completed your first composable capable of drawing a price on a mobile device. Note that you can test your view thanks to @Preview annotation. To see it in action, you can create another Composable function using this annotation. You’ll see the preview within a side panel in Android Studio.
Small conditional changes
In our final composable, we would like to handle various styles based on various parameters such as discount or not. To achieve this goal, we can improve our previous composable function to update its colors according to the model Price in input.
In this example, we check if we want to display our PriceBlock with a promo or not (price.promo != null) and according to the result, we use red or yellow for the background and white or black for the text color.
To see the difference between a price with a promotion or not in our preview panel, we can create another preview function in the same file.
Inline multiple Composable
When we show a price with a promo, we display the strikeout price and the discount percentage above it. These elements are drawn next to each other with a spacing. To define a line, you can use Row and all children inside this component will be drawn on a line.
We declare two texts, one for the strikeout price and the other for the percentage in a Row. To cross out the base price, we just have to add a textDecoration properly sets to LineThrough. For the spacing, you have many solutions but the simplest way is to declare a Spacer component with a modifier to fix the width.
We’ve created 2 small components with a single responsibility, we can combine them to create a final component to display a price component who reacts differently if the price contains a promo or not.
We’ve encapsulated our two previous components inside a Column to draw them next to each other but vertically and we call PriceStrikeoutBanner only if promo attribute is not null in price model. If you want to see how it looks, just create another preview function for the composable state you want to check.
In this post, we’ve taken a quick dive to create Composable component with some simple conditions.