Now it's time to take a closer look at Jetpack Compose and learn the details about what Composable functions are and how to create them. In addition, we will learn how to preview Composables using the Preview annotation, and consider its main features. To do this, we will create a project with Jetpack Compose, perhaps the first in your life.
Project creation
Before we start, it's worth noting that you don't have to create a new project to start using Compose, even if you're already using the View system with XML format Layouts in your app. You can use both if you wish. However, you'll likely want to gradually move all UI Layouts and their elements into Composables step by step or create everything from scratch using Compose.
To start using Jetpack Compose in an existing project, you only need to add a few dependencies and some build configurations. For more detailed information, you can read the official documentation.
In this topic, we'll look at the option of creating a project from scratch with a preconfigured Jetpack Compose template in Android Studio. Let's get down to business!
When creating a new project (File > New > New Project), two preset templates are available: Empty Activity (or Empty Compose Activity in an older version of Android Studio).
Preinstalled project templates
The next step is to choose a name for your application and a minimum SDK.
Jetpack Compose requires a minimum SDK of Android API version 21 or higher.
Project Configuration
This is what the MainActivity.kt file of the project template with Compose framework will look like:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HyperskillTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
HyperskillTheme {
Greeting("Android")
}
}But let's first look at the Greeting Composable function and understand how it works and what it does.
Composables
Composable functions, or simply composables, are regular Kotlin functions annotated with the @Composable annotation. The specified annotation informs the compiler that the given function describes a certain part of the application's UI. Like regular functions, composables can take data as arguments, including other composables, handle them in a specific way, and pass the specified data to internal composables.
Unlike the convention for naming regular Kotlin functions, which use the camelCase style, Composable functions should be named starting with a capital letter in the PascalCase style.
Consider the already created function Greeting of the default layout of our project.
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name!")
}This function is composable because it's annotated with the corresponding annotation. It takes a String value as its single parameter name. The body of this function calls another function, Text, a default composable of the Jetpack Compose library, but we'll look at it in more detail in the topics to come. In turn, the Composable function Text takes the String template "Hello, $name" as its text parameter and is responsible for displaying this text element of the UI on the screen.
So, in the future, in order to display a greeting message on the screen, we don't need to recreate a greeting each time separately for each person. You can simply call the composable Greeting with the required name as many times as you need. As you can see in the example, the Greeting composable function is passed as a parameter to the higher-order function, Surface, which in turn is also composable. It is a surface container with a background color set by the application's theme. The theme name depends on the application name, in our case, it's a HyperskillTheme. For now, we will not dive deep into how it works and why. We will return to this issue in topics dedicated to Theming. In this case, HyperskillTheme is the root composable object in the UI hierarchy of this app's components.
Graph of Composables
Let's try to remove the annotation and see what happens. As you can see, the compiler immediately reports an error: "Functions which invoke Composable functions must be marked with the @Composable annotation". At the same time, we can freely use regular Kotlin functions inside composable ones. Also, nothing prevents you from using composable within conditions and loops. For example, to display a nice-looking greeting, if the name parameter is empty, we can write something like this:
@Composable
fun Greeting(name: String) {
if (name.isNotEmpty()) {
Text(text = "Hello, $name")
} else {
Text(text = "Hello, Compose!")
}
}Preview
For the convenience of building a UI, an important feature is the ability to see the result of the written code quickly. Android Studio has the composable preview tool to preview the UI without having to run the app in an emulator or on a device. You have two ways to preview composables. The first one is applicable if you're not worried about the preview matching the theme options. It should not make any difference if the Composable has no parameters or only has parameters with default arguments. In such a case, you can just add a @Preview annotation to this composable. Otherwise, there is another way. You can create an additional Composable function and annotate it with the @Preview annotation, similar to how it is done in DefaultPreview. The body of this function should contain the theme used by your application, in our case, it's HyperskillTheme. In turn, HyperskillTheme takes the composables that you want to see in the preview as a parameter:
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
HyperskillTheme {
Greeting("")
}
}Also, as you can see, the @Preview annotation has several options that allow you to customize what the preview should look like. We'll consider all of them in the topic on Preview functions.
To show or hide the preview panel, click on one of the buttons , which are located on the top right side of the Android Studio window. When making changes to composables, you may need to rebuild the preview using the corresponding "Build & Refresh" button (Ctrl+Shift+F5).
Conclusion
Composable functions are the main UI building blocks in the Jetpack Compose framework. All composables must be marked with the corresponding annotation, due to which the compiler can recognize and process them in a certain way. In addition, you should always keep in mind that composables can only be called within other composables, forming more complex UI components.
Also, an integral part of your work will be the use of Preview functions, with the help of which you can quickly visualize your code without running your application. Enjoy it!