How to Create realistic UI with Jetpack Compose(Part II

We introduced the basic concepts of Jetpack Compose in our previous article, Saying Hello to Jetpack Compose.

Jetpack Compose is a new way to declaratively build Android app UIs. Now you can write an Android APP without any XML.

Can YOU really build uIs without XML?

Yes! With the latest Jetpack Compose, a modern UI tool, you can do just that. Compose builds the UI by simply defining a Composable function that receives the data and renders the UI elements.

A few key points of Jetpack Compose’s declarative UI design pattern:

  • Improved development efficiency: full compatibility with existing code.
  • Less code: You can do more with less code while avoiding whole class problems, so the code is cleaner and easier to maintain.
  • More powerful tools: You can create more attractive apps by taking advantage of the apis provided by the Android platform.
  • Intuitive thinking: You just need to describe the UI and leave the rest to Compose. The UI updates automatically every time the state changes.

In this article, we will create a UI from Dribbble Shots Flower app and learn how to build a simple UI using Jetpack Compose. Let’s get started without wasting your time.

Quick start

To start Jetpack Compose, you need to configure a set of Gradle dependencies.

//App level build.gradle
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.ui:ui-tooling:$compose_version" 
Copy the code

The compose flag also needs to be set to true, which is in the buildFeatures block below Android.

//App level build.gradle
buildFeatures {
    compose true
}
Copy the code

Compose APP entry

Because Jetpack Compose builds the UI programmatically, you don’t need any XML anymore. So instead of calling setContentView(r.layout.activity_main), you need to build the setContent method.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)

        setContent {
            Text("Hello, World!")}}}Copy the code

Let’s create a list of flowers to show some basic information

If we need to design more than these elements of the UI, we may also need linear layouts, relative layouts, or constrained layouts to achieve a better design.

In order to achieve the same effect in Jetpack, we need to use some special containers, such as Column.

Column { 
    //Write your design here
}
Copy the code

As the function name describes, this function lays out its children vertically. Here we have an example of laying out two Text components vertically.

@Composable
fun FlowerCard(flower: Flowers){
    Column {
        Text(
            text = flower.name,
            style = TextStyle(
                color = gray,
                fontSize = 16.sp
            )
        )
        Text(
            text = flower.price,
            style = TextStyle(
                color = colorPrimary,
                fontSize = 16.sp
            )
        )
    }
Copy the code

Now we add a plus button to the flower message.

As you might expect, you can use the Row() function to lay out child elements horizontally. The default configuration is for all child elements to be laid out next to each other, with no gaps.

@Composable
fun FlowerCard(flower: Flowers){
    Row(modifier = Modifier.padding(20.dp)) {
        Column(modifier = Modifier.weight(1f)) {
            Text(
                text = flower.name,
                style = TextStyle(
                    color = gray,
                    fontSize = 16.sp
                )
            )
            Text(
                text = flower.price,
                style = TextStyle(
                    color = colorPrimary,
                    fontSize = 16.sp
                )
            )
        }
        IconButton(
            onClick = { },
            modifier = Modifier.background(
                color = colorPrimary,
                shape = RoundedCornerShape(10.dp)
            )
        ) {
            Icon(Icons.Default.Add, tint = Color.White)
        }
    }
}
Copy the code

In the above code, we added the spacing through the Modifier. But what exactly is the Modifier? Modifier is an ordered, immutable collection of elements that decorate or add behavior to the Compose UI element, such as background, spacing, click events, and so on.

Now let’s wrap a layer of Card on top of row.

@Composable
private fun FlowerCard(flower: Flowers) {
    Card(
        shape = RoundedCornerShape(14.dp),
        backgroundColor = Color.White,
        modifier = Modifier.padding(10.dp).width(180.dp)
    ) {
        Row(modifier = Modifier.padding(20.dp)) {
            Column(modifier = Modifier.weight(1f)) {
                Text(
                    text = flower.name,
                    style = TextStyle(
                        color = gray,
                        fontSize = 16.sp
                    )
                )
                Text(
                    text = flower.price,
                    style = TextStyle(
                        color = colorPrimary,
                        fontSize = 16.sp
                    )
                )
            }
            IconButton(
                onClick = { },
                modifier = Modifier.background(
                    color = colorPrimary,
                    shape = RoundedCornerShape(10.dp)
                )
            ) {
                Icon(Icons.Default.Add, tint = Color.White)
            }
        }
    }
}
Copy the code

Card has very rich properties. If you want a circle or other shape, use the modifier to add spacing, width, and height to the card. Card can display information as a child element.

Now we want to add the picture of the flower to the flower information. That is, we want to display multiple information on the Card, but we know that the Card can only accept one child element. So we have to use Column.

@Composable
private fun FlowerCard(flower: Flowers) {
    Card(
        shape = RoundedCornerShape(14.dp),
        backgroundColor = Color.White,
        modifier = Modifier.padding(10.dp).width(180.dp)
    ) {
        Column(
            modifier = Modifier.fillMaxWidth().padding(10.dp),
        ) {
            Image(
                modifier = Modifier.size(140.dp),
                asset = imageResource(id = flower.image)
            )
            Row(modifier = Modifier.padding(top = 20.dp)) {
                Column(modifier = Modifier.weight(1f)) {
                    Text(
                        text = flower.name,
                        style = TextStyle(
                            color = gray,
                            fontSize = 16.sp
                        )
                    )
                    Text(
                        text = flower.price,
                        style = TextStyle(
                            color = colorPrimary,
                            fontSize = 16.sp
                        )
                    )
                }
                IconButton(
                    onClick = { },
                    modifier = Modifier.background(
                        color = colorPrimary,
                        shape = RoundedCornerShape(10.dp)
                    )
                ) {
                    Icon(Icons.Default.Add, tint = Color.White)
                }
            }
        }
}
Copy the code

In the above code, we used Image to add an Image.

The asset property is used to provide image resources. The imageResource function takes an image ID as an argument and displays the ImageAsset on the View. Image also has many other properties such as scaling, aligning, changing the presentation of the Image’S UI, and so on.

Create a flower list

Usually to create a list you use RecyclerView. Similarly, in Jetpack Compose we use LazyRowFor. This is a horizontal list that lays out only the items currently displayed.

Now put it all together and create PopularFlowersList().

@Composable
private fun PopularFlowersList(a) {
    LazyRowFor(
        items = FlowersData.list,
        modifier = Modifier.fillMaxWidth()
    ) { flowers ->
        FlowerCard(flowers)
    }
}
Copy the code

Congratulations, you have successfully created your first real UI with Jetpack Compose.

Note: Because Jetpack Compose is currently in alpha (currently in beta), components may change their properties.

Here’s the Github link for the example

This article is just the beginning of the series, and in subsequent articles we plan to write an example using MVVM design patterns. So please stay tuned and we will continue to work on!!