Exploring Jetpack Compose
Nowadays most happening topic in the android dev community is Jetpack Compose, a new way of creating the UI.
Before touching jetpack compose we should understand the basics of Declarative UI. In Declarative UI, design UI by means of code. Jetpack compose is kind of inspired by React js and flutter.
Today we will try to build our first UI using Jetpack compose.
Now let's create new android projects in the canary version of the android studio which supports the compose feature with the built-in ability to create empty compose activity with preview option. You can download the android studio from here.
Once you create the new project you will land on MainActivity with simple text with Hello Android. Let's go through some basic components of compose.
In the compose way, we use setContent for setting the view which will be visible when the activity launches. The basic thumb rule when you are creating any view using a function should be annotated by @Composable
@Composable
fun MyView() {
Text("Hello guys")
}
Composable functions are fundamental building blocks of an application built with Compose.
Text() is a composable function that takes many arguments but text argument is mandatory to display text. We can also set the style for text using style param which accepts typography type with many options from h1 to h6 which is like HTML tags. There are many options available with each having a unique purpose.
@Composable
fun MyView() {
Column {
Text("Hello Guys", style = typography.h4)
Text("This is my fist composable function", style = typography.h5)
}
}
The column is a composable function that places its children in a vertical sequence. Column accepts the lambda which holds the children.
@Composable
fun MyView() {
Row {
Text("Name:")
Text("John")
}
}
Similarly, if you want to display anything horizontally we can use Row.
Button(onClick = {
//do some action here
}) {
Text("Click me")
}
There is a Button composable function that accepts onClick. Which is lambda just like clickListener in normal Button and we can add text to a button using another lambda, we are calling Text function in that lambda.
TopAppBar(
backgroundColor = MaterialTheme.colors.primaryVariant,
contentColor = Color.White,
title = {
Text(text = "Tutorial")
},
navigationIcon = {
IconButton(onClick = { finish() }) {
Icon(Icons.Filled.ArrowBack)
}
},
actions = {
IconButton(onClick = {}) {
Icon(Icons.Filled.Favorite)
}
IconButton(onClick = {}) {
Icon(Icons.Filled.AccountBox)
}
},
elevation = 4.dp
)
TopAppBar is a built-in Toolbar with the option of setting backgroundColor, contentColor which sets the color of text inside and provides the title with a lambda option. There is navigationIcon argument which accepts lambda in which you can add IconButton where you can mention the Back button , Menu button or any button with onClick action. If you want any action button at end of TopAppBar there is an actions param that accepts lambda where you can provide IconButton again.
The most widely used component and my favorite which brings the finishing to any layout is Card.
Card(
elevation = 4.dp,
border = BorderStroke(1.dp, Color.LightGray),
modifier = Modifier.padding(16.dp).fillMaxWidth()
) {}
In the card function, we can provide the elevation which will lift the card, the border will add a border with width and color of the border and there is a modifier argument is currently accepting padding. This will give you a beautiful card with shadow and margin around.
We will cover many more composable functions and their properties today in the below list of items which is equivalent to RecyclerView.
The best part of compose library is creating lists with a view that is really simple.
@Composable
private fun CountryListView() {
val countries = countryList()
LazyColumnFor(items = countries) { country ->
Card(
elevation = 4.dp,
border = BorderStroke(1.dp, Color.LightGray),
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
top = 8.dp,
bottom = 8.dp,
).fillMaxWidth(),
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(country.name, style = typography.h4)
Text(country.capital, style = typography.body1)
}
}
}
}
To create the list we need 1 list of items, In the above example, we are using a list of countries.
There is LazyColumnFor composable function. It takes a list of items (in our case which is countries which we want to display)and builds each item on demand. We can have any number of items on the list. Only items that are visible will be composed just like RecyclerView.
There is 1 more variant which is LazyColumnForIndexed this variant will give you an index of item and item as well.
LazyColumnForIndexed(items = countries) { index, country ->
}
By using index we can manage some logic like load more items or highlight any item with a specific index.
@Composable
private fun CountryListHorizontal(){
val countries = countryList()
LazyRowFor(items = countries) { country ->
Card(
elevation = 4.dp,
border = BorderStroke(1.dp, Color.LightGray),
modifier = Modifier.padding(
start = 8.dp,
end = 8.dp,
top = 16.dp,
bottom = 16.dp,
).fillMaxWidth(),
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(country.name, style = typography.h4)
Text(country.capital, style = typography.body1)
}
}
}
}
Similarly, we can have a horizontal list using LazyRowFor.
Today we covered some basic components. This is just the start of the Compose library. We will try to cover more components and properties in upcoming articles.
Compose library is still in alpha and many more changes are yet to come. Please refer to the official documentation for Compose Library in case of any doubt.
Please find the git repo for the above examples here.
If you like this article please click the 👏 button and share it to help others! and let me know the feedback.