Building UI Using Jetpack Compose in Android - GeeksforGeeks

15 Nov, 2021
Jetpack Compose is a modern UI toolkit that is designed to simplify UI development in Android. It consists of a reactive programming model with conciseness and ease of Kotlin programming language. It is fully declarative so that you can describe your UI by calling some series of functions that will transform your data into a UI hierarchy. When the data changes or is updated then the framework automatically recalls these functions and updates the view for you.
Prerequisites:
Familiar with Kotlin and OOP Concepts as wellBasic understanding about Jetpack ComposeAndroid Studio
Familiar with Kotlin and OOP Concepts as well
Basic understanding about Jetpack Compose
Android Studio
So, we are just going to create an application UI using jetpack compose (Kotlin). our final UI will look like it.
Media error: Format(s) not supported or source(s) not found
It’s’ an easy UI to build using jetpack compose but a little bit hard using XML. So, let’s start step by step.
Step 1: Create a new android studio project
To create a new project in Android Studio using Jetpack Compose please refer to:- How to Create a New Project in Android Studio Canary Version with Jetpack Compose.
Step 2: Let’s Add resources to the project
There are some resources like colors, image assets, fonts, and some little things. You can easily find them otherwise just get them from the GitHub repo.
Step 3: Create a Kotlin class HomeScreen.kt
We can do the same task in MainActivity.kt as well, but it’s good practice to create another file. Initially, we start from the top, so creating the first header of the UI. having two texts with an image of a search icon. Things are very easy in this case we just create functions and call them, and that is how we can reuse the code very easily.
Kotlin
package com.cuid.geekscourse.ui.theme import androidx.compose.foundation.backgroundimport androidx.compose.foundation.layout.*import androidx.compose.material.Iconimport androidx.compose.material.MaterialThemeimport androidx.compose.material.Textimport androidx.compose.runtime.Composableimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.res.painterResourceimport androidx.compose.ui.tooling.preview.Previewimport androidx.compose.ui.unit.dpimport com.cuid.composeui.R // here we have created HomeScreen function// and we will call all functions inside it.// and finally just call this function from mainActivity@Composablefun HomeScreen() {      // this is the most outer box that will      // contain all the views,buttons,chips,etc.    Box(        modifier = Modifier            .background(DeepBlue)            .fillMaxSize()    ) {        Column {              // this is how we call              // function adding whole UI            GreetingSection()        } }      @Composable // and this is the function// just for creating header at topfun GreetingSection(    name: String = "Geeks") {      // here we just arrange the views    Row(        horizontalArrangement = Arrangement.SpaceBetween,        verticalAlignment = Alignment.CenterVertically,        modifier = Modifier            .fillMaxWidth()            .padding(15.dp)    ) {        Column(            verticalArrangement = Arrangement.Center        ) {              // heading text view            Text(                text = "Good morning, $name",                style = MaterialTheme.typography.h1            )            Text(                text = "We wish you have a good day!",                style = MaterialTheme.typography.body1            )        }        // search icon        Icon(            painter = painterResource(id = R.drawable.ic_search),            contentDescription = "Search",            tint = Color.White,            modifier = Modifier.size(24.dp)        )    }}
Step 4: Create another function for chips
As we have shown above in-app preview that we can change chips. So let’s build it.
Kotlin
// This is how we can create chip seaction at the top of app @Composablefun ChipSection(     // function with single argument    chips: List<String>) {    var selectedChipIndex by remember {        // it will not update the string        // but save and it will helpful for us        mutableStateOf(0)    }    LazyRow {        items(chips.size) {            Box(                contentAlignment = Alignment.Center,                modifier = Modifier                    .padding(start = 15.dp, top = 15.dp, bottom = 15.dp)                    .clickable {                        selectedChipIndex = it                    }                    .clip(RoundedCornerShape(10.dp))                    .background(                        // this is basic condition for selected chip index                        if (selectedChipIndex == it) ButtonGreen                        else DarkerButtonGreen                    )                    .padding(15.dp)            ) {                Text(text = chips[it], color = TextWhite)            }        }    }}
Step 5: Create a function for SuggestionSecation
It’s really a very basic part of this app. 
Kotlin
// This function is for suggestion secation @Composablefun SuggestionSection(    color: Color = LightBlue) {    Row(           verticalAlignment = Alignment.CenterVertically,        horizontalArrangement = Arrangement.SpaceBetween,        modifier = Modifier            .padding(15.dp)            .clip(RoundedCornerShape(10.dp))            .background(color)            .padding(horizontal = 15.dp, vertical = 20.dp)            .fillMaxWidth()    ) {        Column {            // here are two text views or we can say only text            Text(                text = "Daily Coding",                  // it can be litile bit confusing but                  // it is just text style alternate                  // of fontfamily in XML                style = MaterialTheme.typography.h2                               )            Text(                // same as above                text = "do at least • 3-10 problems / day",                style = MaterialTheme.typography.body1,                color = TextWhite            )        }        Box(            // box containing icon            contentAlignment = Alignment.Center,            modifier = Modifier                .size(40.dp)                .clip(CircleShape)                .background(ButtonGreen)                .padding(10.dp)        ) {            Icon(                painter = painterResource(id = R.drawable.ic_play),                contentDescription = "Play",                tint = Color.White,                modifier = Modifier.size(16.dp)            )        }    }}
The next step should be the card of courses but that is not easy or we can say the toughest part of the whole UI, so we will do it after the last one.
Let’s Create a BottomSection, but before that, we should create the class for simplicity
because our BottomSection element has two fields or views so let’s do
Step 6: Create Class for ButtomSection (BottomMenuContent.kt)
Kotlin
package com.cuid.geekscourses import androidx.annotation.DrawableRes// having two parameters title and iconiddata class BottomMenuContent(    val title: String,    @DrawableRes val iconId: Int)
Step 7: Create function for ButtomSection 
Kotlin
@Composable// this function tells us that// how menu item should look likefun BottomMenu(    items: List<BottomMenuContent>,    modifier: Modifier = Modifier,    activeHighlightColor: Color = ButtonGreen,    activeTextColor: Color = Color.White,    inactiveTextColor: Color = AquaBlue,    initialSelectedItemIndex: Int = 0) {    var selectedItemIndex by remember {               mutableStateOf(initialSelectedItemIndex)    }    Row(        horizontalArrangement = Arrangement.SpaceAround,        verticalAlignment = Alignment.CenterVertically,        modifier = modifier               .fillMaxWidth()            .background(DeepBlue)            .padding(15.dp)    ) {          // it is basically what we should have          // for creating an element of BottomMenuItem        items.forEachIndexed { index, item ->            BottomMenuItem(                item = item,                isSelected = index == selectedItemIndex,                activeHighlightColor = activeHighlightColor,                activeTextColor = activeTextColor,                inactiveTextColor = inactiveTextColor            ) {                selectedItemIndex = index            }        }    }}// it's basically how menu item should look like@Composablefun BottomMenuItem(    item: BottomMenuContent,    isSelected: Boolean = false,    activeHighlightColor: Color = ButtonGreen,    activeTextColor: Color = Color.White,    inactiveTextColor: Color = AquaBlue,    onItemClick: () -> Unit) {    Column(        horizontalAlignment = Alignment.CenterHorizontally,        verticalArrangement = Arrangement.Center,        modifier = Modifier.clickable {            onItemClick()        }    ) {          // here are some peremetens          // for how elements will align        Box(            contentAlignment = Alignment.Center,            modifier = Modifier                .clip(RoundedCornerShape(10.dp))                .background(if (isSelected) activeHighlightColor else Color.Transparent)                .padding(10.dp)        ) {            Icon(                painter = painterResource(id = item.iconId),                contentDescription = item.title,                tint = if (isSelected) activeTextColor else inactiveTextColor,                modifier = Modifier.size(20.dp)            )        }        Text(            text = item.title,              // it's basic condition            color = if(isSelected) activeTextColor else inactiveTextColor        )    }}
Now, the final part of the app is a little bit tricky, which is nothing but the course item, this one:
course item
Here we have three colors, string and icon as well, then  same as above we will create a class, and set data during the function call
Step 8: Creating Class Course.kt
This section has five fields, so create five variables of their types. The fields you can see in the code as well.
Kotlin
package com.cuid.geekscourses import androidx.annotation.DrawableResimport androidx.compose.ui.graphics.Color data class Course(    val title: String,    @DrawableRes val iconId: Int,    val lightColor: Color,    val mediumColor: Color,    val darkColor: Color)
Now just think about it, that how to make those curves on the card. So basically, we set some points and create a smooth curve by joining points created
Step 9: Creating CourseSection
It’s basically just how our grid will Arrange.
Kotlin
@ExperimentalFoundationApi@Composable// here we have just passed the list of coursesfun CourseSection(courses: List<Course>) {    Column(modifier = Modifier.fillMaxWidth()) {        Text(            text = "courses",            style = MaterialTheme.typography.h1,            modifier = Modifier.padding(15.dp)        )        // we have used lazyVertically grid        LazyVerticalGrid(            cells = GridCells.Fixed(2), // it basically tells no. of cells in a row            contentPadding = PaddingValues(start = 7.5.dp, end = 7.5.dp,bottom = 100.dp),            modifier = Modifier.fillMaxHeight()        ) {            items(courses.size) {              // here we have to define how one of these item is look like              // we will tell after defining item design              // let me comment it for now and after              // creating you just have to remove                             // CourseItem(course = courses[it])            }        }    }}
Step 10: Creating Course Card Item Design
Kotlin
@Composablefun CourseItem(    course: Course) {    BoxWithConstraints(          // Box with some attributes        modifier = Modifier            .padding(7.5.dp)            .aspectRatio(1f)            .clip(RoundedCornerShape(10.dp))            .background(feature.darkColor)    ) {        val width = constraints.maxWidth        val height = constraints.maxHeight        // setting 5 points for medium        // color or we can say for another        // Medium colored path        val mediumColoredPoint1 = Offset(0f, height * 0.3f)        val mediumColoredPoint2 = Offset(width * 0.1f, height * 0.35f)        val mediumColoredPoint3 = Offset(width * 0.4f, height * 0.05f)        val mediumColoredPoint4 = Offset(width * 0.75f, height * 0.7f)        val mediumColoredPoint5 = Offset(width * 1.4f, -height.toFloat())        // joining points to make curves with the help of path class        // path file that we have created earlier        // having function that just help to reduce our code        // and the function is standardQuadFromTo(m1,m2) taking        // two peramente and connect them        val mediumColoredPath = Path().apply {            moveTo(mediumColoredPoint1.x, mediumColoredPoint1.y)            standardQuadFromTo(mediumColoredPoint1, mediumColoredPoint2)            standardQuadFromTo(mediumColoredPoint2, mediumColoredPoint3)            standardQuadFromTo(mediumColoredPoint3, mediumColoredPoint4)            standardQuadFromTo(mediumColoredPoint4, mediumColoredPoint5)            lineTo(width.toFloat() + 100f, height.toFloat() + 100f)            lineTo(-100f, height.toFloat() + 100f)            close()        }        // it's another part of that          // texture with light color        // Light colored path        val lightPoint1 = Offset(0f, height * 0.35f)        val lightPoint2 = Offset(width * 0.1f, height * 0.4f)        val lightPoint3 = Offset(width * 0.3f, height * 0.35f)        val lightPoint4 = Offset(width * 0.65f, height.toFloat())        val lightPoint5 = Offset(width * 1.4f, -height.toFloat() / 3f)         val lightColoredPath = Path().apply {            moveTo(lightPoint1.x, lightPoint1.y)            standardQuadFromTo(lightPoint1, lightPoint2)            standardQuadFromTo(lightPoint2, lightPoint3)            standardQuadFromTo(lightPoint3, lightPoint4)            standardQuadFromTo(lightPoint4, lightPoint5)            lineTo(width.toFloat() + 100f, height.toFloat() + 100f)            lineTo(-100f, height.toFloat() + 100f)            close()        }        // canvas is used when we          // want to draw something        Canvas(            modifier = Modifier                .fillMaxSize()        ) {            drawPath(                  // function for drawing paths                  // just pass the path                path = mediumColoredPath,                color = course.mediumColor            )            drawPath( // it's for the lighter path                path = lightColoredPath,                color = course.lightColor            )        }         // so , we have done with texture and         // now just creating box and other things        // box containing course elements        Box(            modifier = Modifier                .fillMaxSize()                .padding(15.dp)        ) {            Text(                text = course.title,                style = MaterialTheme.typography.h2,                lineHeight = 26.sp,                modifier = Modifier.align(Alignment.TopStart)            )            Icon(                painter = painterResource(id = course.iconId),                contentDescription = course.title,                tint = Color.White,                modifier = Modifier.align(Alignment.BottomStart)            )            Text(                text = "Start",                color = TextWhite,                fontSize = 14.sp,                fontWeight = FontWeight.Bold,                modifier = Modifier                    .clickable {                        // Handle the clicks                    }                    .align(Alignment.BottomEnd)                    .clip(RoundedCornerShape(10.dp))                    .background(ButtonGreen)                    .padding(vertical = 6.dp, horizontal = 15.dp)            )        }    }}
That’s all about, how our item will look like. So just pass the item in the course section
CourseItem(course = courses[it])
It’s that file that we have discussed above to reduce our code
Kotlin
package com.cuid.geekscourses import androidx.compose.ui.geometry.Offsetimport androidx.compose.ui.graphics.Pathimport kotlin.math.abs// The function is standardQuadFromTo(m1,m2)// taking two peramente those are nothing but points// that we are created and just add.fun Path.standardQuadFromTo(from: Offset, to: Offset) {      // this function is basically draw      // a line to our second point and      // also smooth on that line and make it curve    quadraticBezierTo(        from.x,        from.y,        abs(from.x + to.x) / 2f,        abs(from.y + to.y) / 2f    )}
Now we have all the things ready so just call all the functions and see your result as 
Kotlin
@ExperimentalFoundationApi@Composablefun HomeScreen() {    // this is the most outer box      // having all the views inside it    Box(        modifier = Modifier            .background(DeepBlue)            .fillMaxSize()    ) {        Column {              // this is the function for header            GreetingSection()            // it's for chipsSecation, and pass              // as many strings as you want            ChipSection(chips = listOf("Data structures", "Algorithms", "competitive programming", "python"))             // function for suggestionSection              suggestionSection()              // this is for course secation            CourseSection(                  // function require list of courses and                  // one course contain 5 attributes                courses = listOf(                    Course(                        title = "geek of the year",                        R.drawable.ic_headphone,                          // these are colors.......                        BlueViolet1,                        BlueViolet2,                        BlueViolet3                    ),                      // below are the copies of the objects                      // and you can add as many as you want                    Course(                        title = "How does AI Works",                        R.drawable.ic_videocam,                        LightGreen1,                        LightGreen2,                        LightGreen3                    ),                    Course(                        title = "Advance python Course",                        R.drawable.ic_play,                        skyblue1,                        skyblue2,                        skyblue3                    ),                    Course(                        title = "Advance Java Course",                        R.drawable.ic_headphone,                        Beige1,                        Beige2,                        Beige3                    ),                    Course(                        title = "prepare for aptitude test",                        R.drawable.ic_play,                        OrangeYellow1,                        OrangeYellow2,                        OrangeYellow3                    ),                    Course(                        title = "How does AI Works",                        R.drawable.ic_videocam,                        LightGreen1,                        LightGreen2,                        LightGreen3                    ),                )            )        }        // this is the final one that is bottomMenu        BottomMenu(items = listOf(              // having 5 instances            BottomMenuContent("Home", R.drawable.ic_home),            BottomMenuContent("explore", R.drawable.ic_baseline_explore_24),            BottomMenuContent("dark mode", R.drawable.ic_moon),            BottomMenuContent("videos", R.drawable.ic_videocam),            BottomMenuContent("Profile", R.drawable.ic_profile),        ), modifier = Modifier.align(Alignment.BottomCenter))    }}
Now add fun HomeScreen() that contains all the functions, in MainActivity as 
Kotlin
package com.cuid.geekscourses import android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.compose.foundation.ExperimentalFoundationApiimport com.cuid.geekscourses.ui.HomeScreenimport com.cuid.geekscourses.ui.theme.Geekscourse class MainActivity : ComponentActivity() {    @ExperimentalFoundationApi    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContent {            Geekscourse{                HomeScreen()            }        }    }}
Finally, Our UI is looking like this:
Output:
Project Link: Click Here
rajeev0719singh
singghakshay
Android-Jetpack
Picked
Android
Kotlin
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
How to Create and Add Data to SQLite Database in Android?
Broadcast Receiver in Android With Example
Resource Raw Folder in Android Studio
Services in Android with Example
CardView in Android With Example
Broadcast Receiver in Android With Example
Android UI Layouts
Kotlin Array
Services in Android with Example
Android RecyclerView in Kotlin