Android Jetpack Compose Example

This tutorial is about Android Jetpack compose and how to use it in an android application with the help of simple Book application.

Jetpack Compose?

Jetpack Compose is a modern toolkit for building native Android UI. Jetpack Compose simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs. 

To use Jetpack Compose you need to use at least a version >= Android Studio Arctic Fox.

Composable Function

In Jetpack Compose, Composable functions are used to define all the UI of your app programmatically. So, you need not use any XML files for the layout of the app. All you need to make a composable function is just by using the @Composable annotation to the function name.

The basic syntax of a Composable function is:

@Composable
fun HelloWorld() {
Text("Hello, World!", style = TextStyle(color = Color.Red))
}

To use HelloWorld() composable function, call it inside setContent() like this:

setContent {
HelloWorld()
}

Previewing a Composable

Android Studio provides an awesome feature of previewing your UI components in the studio itself and that too dynamically. So, whenever you want to test some UI components, then you can simply preview it in the Android Studio by making a Composable function and by using the @Preview annotation.

Example:

@Composable
@Preview
fun HelloWorld() {
Text("Hello, World!", style = TextStyle(color = Color.Red))
}

After you import the annotation, you’ll see the preview of the composable show up in the preview on the right-hand side of the screen.

NOTE: You can’t pass any parameter to a Preview Composable function.

Creating BookApp

Let’s create a project which will contain two screens, first screen will display list of items (each item will contain information about a book) and on click of each item will open a second screen which will display the information of the clicked item.

Gradle Dependencies

Add this inside in the android{} block of your build.gradle

android{
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion "1.0.3"
kotlinCompilerVersion '1.5.30'
}
}

Add the below Compose dependencies mainly used while working with jetpack compose.

dependencies{

def composeVersion = "1.0.1"

implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation 'androidx.activity:activity-compose:1.3.0-alpha06'
}
Code Implementation

1. The MainActivity.kt file represents the first screen which consist of a list.

MainActivity.kt

package com.c1ctech.jetpackcomposeexp

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.DrawableRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.startActivity
import com.c1ctech.jetpackcomposeexp.ui.theme.JetpackComposeExpTheme
import kotlinx.android.parcel.Parcelize
import androidx.compose.foundation.Image as Image


val bookList: List<Book> = listOf(
Book(R.drawable.anny_frank, "The Diary of A Young Girl", "Anne Frank"),
Book(R.drawable.alexander_the_great, "Alexander the Great", "Jacob Abbott"),
Book(R.drawable.autobiography_of_a_yogi, "Autobiography of a Yogi", "Paramahansa Yogananda"),
Book(R.drawable.fluffy_and_me, "Fluffy and Me", "Anita Krishan"),
Book(R.drawable.my_inventions, "My Inventions", "Nikola Tesla"),
Book(R.drawable.the_enchanted_castle, "The Enchanted Castle", "E. Nesbit"),
Book(R.drawable.the_secret_garden, "The Secret Garden", " Frances Hodgson Burnett")
)


class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetpackComposeExpTheme {
Column(modifier = Modifier.fillMaxSize()) {
//Material Design top app bar displays information
// and actions relating to the current screen.
TopAppBar(title = {
Text("BookApp")
})
BookList(bookList, this@MainActivity)
}
}
}
}
}

//creating data class Book, which implements Parcelable
@Parcelize
data class Book(
@DrawableRes val imageResource: Int,
val bookTitle: String,
val bookAuthor: String
) : Parcelable

@Composable
fun BookList(books: List<Book>, context: Context) {
//The vertically scrolling list that only composes
// and lays out the currently visible items.
LazyColumn() {
items(books) { book ->
BookListItem(book, context)
}
}
}

@Composable
fun BookListItem(book: Book, context: Context) {
//used to make a CardView.
Card(
shape = RoundedCornerShape(8.dp),
elevation = 8.dp,
modifier = Modifier
.padding(16.dp)
.clickable {
//passing book instance to DetailActivity
//open DetailActivity on item click
val intent = Intent(context, DetailActivity::class.java)
intent.putExtra("bookData", book)
startActivity(context, intent, null)

}
) {
//places its children in a horizontal sequence.
Row(
modifier = Modifier
.padding(8.dp)
) {
BookImage(book)
//places its children in a vertical sequence.
Column(
modifier = Modifier
.weight(6f, true)
.padding(20.dp, 0.dp, 0.dp, 0.dp),
) {
//used to display text
Text(
text = book.bookTitle,
style = MaterialTheme.typography.subtitle1,
color = Color.Red
)
Text(
text = "by ${book.bookAuthor}",
style = MaterialTheme.typography.subtitle2,
fontStyle = FontStyle.Italic,
fontWeight = FontWeight.Bold,
color = Color.Blue,
)

}
}
}
}

@Composable
fun BookImage(book: Book?) {
//used to display an image.
Image(
painter = painterResource(book!!.imageResource),
contentDescription = null,
contentScale = ContentScale.FillBounds,
modifier = Modifier
.size(84.dp)
.clip(RoundedCornerShape(corner = CornerSize(8.dp)))
)
}

//Preview can be applied to @Composable methods with no parameters
//to show them in the Android Studio preview.
@Preview
@Composable
fun bookListPreview() {
JetpackComposeExpTheme {
Column(modifier = Modifier.fillMaxSize()) {
TopAppBar(title = {
Text("BookApp")
})
BookList(
bookList,
LocalContext.current
)
}
}
}
  • Column: A Column is a layout composable which simply lays out all its child composables in a vertical column. It is similar to LinearLayout with vertical orientation. 
  • Lazy Column: The vertically scrolling list that only composes and lays out the currently visible items.
  • Card: A Card is a layout composable that is used to make a CardView.
  • Clickable: makes a composable react with the user by using Clickable. Clickable supports a one-time click, double click, and long press.
  • Image: To display an image, we can use Image composable.

2. The DetailActivity.kt file represents the second screen, which will open on click of each item.

DetailActivity.kt

package com.c1ctech.jetpackcomposeexp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

class DetailActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
//passing book instance from composable function
BookImageFullScreen(intent.getParcelableExtra("bookData"))
}
}
}

@Composable
fun BookImageFullScreen(book: Book?) {
Image(
painter = painterResource(book!!.imageResource),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.padding(16.dp)
)
}

When you run the app it will look like this:

       

Leave a Reply