Android Development 04: Jetpack Compose


What is Jetpack Compose
Jetpack Compose is a modern toolkit for building Android UIs. Compose simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin capabilities. With Compose, you can build your UI by defining a set of functions, called composable functions, that take in data and describe UI elements.
Composable functions
Composable functions are the basic building block of a UI in Compose. A composable function:
Describes some part of your UI.
Doesn't return anything.
Takes some input and generates what's shown on the screen.
Annotations can take parameters. Parameters provide extra information to the tools processing them. The following are some examples the
@Preview
annotation with and without parameters.Jetpack Compose is built around composable functions. These functions let you define your app's UI programmatically by describing how it should look, rather than focusing on the process of the UI's construction. To create a composable function, just add the
@Composable
annotation to the function name.Composable functions can accept arguments, which let the app logic describe or modify the UI. In this case, your UI element accepts a
String
so that it can greet the user by name.
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
Greeting("Android")
}
}
UI Hierarchy
- The UI hierarchy is based on containment, meaning one component can contain one or more components, and the terms parent and child are sometimes used.
- The three basic, standard layout elements in Compose are
Column
,Row
, andBox
composables. You learn more about theBox
composable in the next codelab.
- example of child UI in jetpack compose:
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Row {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
)
Text(
text = from,
fontSize = 36.sp
)
}
}
Example code:
package com.example.happybirthday
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.happybirthday.ui.theme.HappyBirthdayTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingText(
message = "Happy Birthday Sam!",
from = "From Emma",
modifier = Modifier.padding(8.dp)
)
}
}
}
}
}
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
)
}
}
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
}
}
Explanation:
Summary for Interview:
"This is a Jetpack Compose-based Android app that uses a
GreetingText
composable to show a birthday message. It uses modern UI practices like theming, column layout, font scaling, and padding. I structured the UI usingSurface
andMaterialTheme
, which ensures design consistency. The use of@Preview
allows rapid development and previewing in Android Studio without rebuilding the app every time."
Manual Dependency injection:
In the Android Studio "Ladybug" version (which corresponds to Android Studio Hedgehog / Iguana timeframe and uses Gradle 8+, AGP 8+, and Kotlin 1.9+), you still need to manually add the ViewModel dependency if you are using Jetpack Compose and want to integrate ViewModel functionality.
Required dependency block:
// ViewModel for Compose implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") // (Optional) ViewModel core for non-Compose usage implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
Replace
2.7.0
with the latest version if a newer one is available.Why Manual?
Even though Jetpack Compose is now well-integrated in Android Studio templates, not all Compose-related libraries (like
viewmodel-compose
) are included by default. Android Studio only adds the core Compose libraries in new projects — you’re expected to add additional Jetpack components like ViewModel, Navigation, or Room manually as needed.
Modifier:
In Jetpack Compose, a Modifier
is a powerful and flexible UI configuration object that is used to:
Change the layout, appearance, behavior, or interaction of a Composable.
Text(
text = "Hello, World!",
modifier = Modifier
.padding(16.dp)
.background(Color.Yellow)
.fillMaxWidth()
)
This means:
Add 16dp padding
Set yellow background
Fill the maximum width
Common Modifier Functions:
Modifier Function | Description |
padding() | Adds padding inside the Composable |
fillMaxWidth() | Makes the Composable take full width |
fillMaxSize() | Makes it take full width & height |
wrapContentSize() | Shrinks to fit content |
size() | Sets fixed width and height |
background() | Sets background color or shape |
clickable() | Makes it respond to clicks |
border() | Adds a border |
align() | Aligns inside a parent like Row /Column |
offset() | Moves the Composable on screen |
Why use Modifier?
It separates concerns:
Composable = What to show
Modifier = How to show it (layout, behavior, style)
@Composable
fun Greeting(name: String) {
Text(
text = "Hello, $name!",
modifier = Modifier
.padding(16.dp)
.background(Color.LightGray)
.clickable { /* handle click */ }
)
}
Image:
Image insertion steps: link
1. Size & Layout
Modifier | Description |
size(100.dp) | Sets fixed width and height |
width(100.dp) / height(100.dp) | Sets width or height separately |
fillMaxWidth() | Fills entire parent width |
fillMaxSize() | Fills entire parent area (width & height) |
wrapContentSize() | Adjusts to image's intrinsic size |
2. Styling & Appearance
Modifier | Description |
clip(RoundedCornerShape(16.dp)) | Clips image corners to shape |
background( Color.Blue ) | Sets a background color behind image |
border(2.dp, Color.Black ) | Adds a border |
alpha(0.5f) | Makes image semi-transparent |
graphicsLayer { ... } | Applies rotation, scale, etc. |
3. Alignment & Positioning
Modifier | Description |
align( Alignment.Center ) | Aligns inside parent layout |
offset(x = 10.dp, y = 5.dp) | Moves image from its original position |
padding(16.dp) | Adds space around the image |
zIndex(1f) | Sets the layering order of UI elements |
4. Interactivity
Modifier | Description |
clickable { ... } | Makes image respond to taps/clicks |
pointerInput { ... } | Detect drag, zoom, gestures |
Example:
Image(
painter = painterResource(id = R.drawable.sample_image),
contentDescription = "Sample Image",
modifier = Modifier
.size(200.dp)
.padding(16.dp)
.clip(RoundedCornerShape(12.dp))
.border(2.dp, Color.Gray)
.clickable { /* onClick action */ }
)
Subscribe to my newsletter
Read articles from Dibyashree Chakravarty directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
