
So now that we’ve understood what Jetpack Compose is and why it matters, let’s actually get our hands dirty.
In this chapter, we’ll:
✅ Set up a new Jetpack Compose project from scratch
✅ Explore what’s different inside the project structure
✅ Learn how to preview composables
✅ And finally, integrate Compose into an existing XML-based project
Let’s get started.
⚙️ Step 1: Creating a New Jetpack Compose Project
Open Android Studio Koala (or Flamingo+ if you’re a time traveler).
From the “New Project” window:
- Select Empty Compose Activity
- Give it a name — let’s call it
FirstComposeApp - Minimum SDK: 21 or higher (Compose doesn’t support below that)
- Click Finish
🎯 Pro Tip: If you pick “Empty Activity” instead of “Empty Compose Activity,” you’ll still get the old XML setup. Always choose Compose Activity when starting fresh.
Once Android Studio finishes building, you’ll notice something instantly different — there’s no XML folder under res/layout.
Because… welcome to a world without XML 😎
🧱 Step 2: Understanding the Project Structure
Let’s walk through what changed in the new project:
🔹 No More res/layout Folder
In XML-based projects, every screen lived inside res/layout.
Compose doesn’t need it — your UI lives entirely in Kotlin files.
So instead of activity_main.xml, you’ll find something like this:
MainActivity.kt
└── setContent {
MyAppTheme {
Greeting("Hello Compose")
}
}
That single setContent {} block replaces all your XML inflation.
🔹 Theme Folder Looks Different
Inside ui/theme/, you’ll see these files:
Color.ktTheme.ktType.ktShape.kt
These handle your app’s Material Design system (colors, shapes, typography).
Think of them like XML’s styles.xml and themes.xml, but written cleanly in Kotlin.
Example snippet from Theme.kt:
@Composable
fun FirstComposeAppTheme(
content: @Composable () -> Unit
) {
MaterialTheme(
colorScheme = LightColorScheme,
typography = Typography,
shapes = Shapes,
content = content
)
}
💡 Dev Trick:
You can define dark and light color palettes here and dynamically switch them using isSystemInDarkTheme().
Example:
val colors = if (isSystemInDarkTheme()) DarkColorScheme else LightColorScheme
MaterialTheme(colorScheme = colors) { ... }
🧩 Step 3: The Magic of setContent {}
Inside your MainActivity, you’ll find this:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FirstComposeAppTheme {
Greeting("Android")
}
}
}
}
This single line — setContent {} — replaces setContentView(R.layout.activity_main) entirely.
💡 How it works:
Everything inside setContent is a Composable tree.
When the app runs, Compose takes that tree, renders it into the UI, and automatically updates it when your state changes.
🧠 Step 4: Create Your First Composable
Open MainActivity.kt and create a simple composable:
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name 👋", fontSize = 24.sp)
}
Then use it inside your content block:
setContent {
FirstComposeAppTheme {
Greeting("Compose Learner")
}
}
Build and run it — you’ll see your first Compose UI on screen.
🎉 Congrats, you just built a full Android UI without touching XML.
👀 Step 5: Using the Preview Feature
In Compose, you can preview your UI without launching the app.
That’s massive for iteration speed.
Add this:
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
FirstComposeAppTheme {
Greeting("Android")
}
}
Now click Split → Design + Code view in Android Studio.
You’ll see your UI render instantly on the right side.
💡 Dev Trick:
You can even create multiple previews to see how your layout behaves on different devices or themes:
@Preview(name = "Light Mode")
@Preview(name = "Dark Mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun MultiPreview() {
Greeting("Compose Rocks!")
}
🔧 Step 6: Adding Compose to an Existing Project
Okay, what if you already have a big XML-based app and don’t want to throw everything away?
No problem — you can integrate Compose gradually.
➕ Add Compose Dependencies
In your module-level build.gradle file, add these:
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.7.4"
}
dependencies {
implementation("androidx.compose.ui:ui:1.7.4")
implementation("androidx.compose.material3:material3:1.3.0")
implementation("androidx.activity:activity-compose:1.9.0")
}
Make sure your Kotlin version is compatible with your Compose compiler.
In 2025, that means Kotlin 2.0+ works best with Compose 1.7+.
💡 Dev Trick:
Always check the official Compose-Kotlin compatibility table before updating.
If they mismatch, your project won’t build.
🧩 Integrate Compose into an XML Layout
You can render a composable inside an existing XML file using ComposeView.
Example (XML):
<androidx.compose.ui.platform.ComposeView
android:id="@+id/composeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Then in your Activity or Fragment:
val composeView = findViewById<ComposeView>(R.id.composeLayout)
composeView.setContent {
Greeting("Compose Inside XML!")
}
Boom — Compose inside XML.
That’s how most hybrid apps migrate: screen by screen.
🧠 Bonus: Common Errors + Quick Fixes
| Issue | Fix |
|---|---|
Unresolved reference: @Composable |
Check if Compose dependency is added and synced. |
Preview not showing |
Make sure function has @Composable + @Preview + no parameters. |
Incompatible Kotlin and Compiler version |
Match versions using Google’s compatibility table. |
| “ComposeView requires AndroidX dependencies” | Enable AndroidX in gradle.properties. |
💡 Dev Trick: When preview doesn’t render, rebuild project with Build → Make Project (Ctrl+F9). 90% of the time, it fixes it.
🎨 Why Compose Project Structure Feels Cleaner
Compose projects are smaller, cleaner, and far easier to scale.
You don’t have dozens of layout XMLs cluttering res/layout.
Instead, you have Kotlin files organized by feature or screen, like this:
ui/
┣ home/
┃ ┣ HomeScreen.kt
┃ ┗ HomeViewModel.kt
┣ profile/
┃ ┣ ProfileScreen.kt
┗ theme/
┣ Color.kt
┣ Shape.kt
┗ Theme.kt
It’s modern. It’s modular. It’s readable.
🧩 Final Thoughts
Jetpack Compose setup might feel like a lot the first time — but once you get it running, it’s unbelievably smooth.
No XML. No adapters. No inflation lag.
Just Kotlin code and real-time UI.
This chapter gave you the foundation — a working project, preview setup, and how to integrate Compose into existing apps.
Next, in Chapter 3, we’ll go deeper: building interactive UIs with state management, layouts, and dynamic recomposition — basically, how Compose thinks.
Written with ❤️ by codewithpk.com
Keep coding. Keep learning. Keep building.
