Pernah nggak sih kamu merasa frustrasi bikin layout Android pakai XML? Nested LinearLayout tiga lapis, constraint yang nggak mau rapi, terus harus bolak-balik antara XML dan Kotlin buat sekadar ganti text. Saya dulu juga begitu. Sampai akhirnya saya coba Jetpack Compose dan rasanya seperti pindah dari motor bebek ke matic - semuanya jadi lebih smooth.
Kalau kamu masih ragu buat mulai belajar Compose, artikel ini bakal jadi panduan lengkap dari nol. Nggak perlu pengalaman Compose sebelumnya. Yang kamu butuhkan cuma dasar Kotlin dan Android Studio yang sudah ter-install.
Jetpack Compose adalah toolkit UI modern dari Google untuk membangun native Android UI. Dirilis stable pertama kali di tahun 2021 dan terus berkembang pesat sampai sekarang. Bedanya dengan cara lama? Compose pakai pendekatan declarative - kamu bilang "seperti ini tampilannya", bukan "lakukan ini lalu itu untuk membuat tampilan".
Dengan XML, kamu punya dua layer: layout XML dan logika di Activity/Fragment. Dengan Compose, semuanya dalam satu file Kotlin. Satu function = satu screen. Lebih simpel, lebih mudah di-maintain.
Google sendiri sudah menjadikan Compose sebagai rekomendasi utama untuk UI Android development. Artinya, kalau kamu mulai project baru di 2026, Compose sudah bukan opsi - tapi standar.
Pertama, buat project baru di Android Studio. Pilih template "Empty Activity" (bukan "Empty Views Activity" - itu untuk XML). Android Studio sudah support Compose dari Arctic Fox ke atas.
Pastikan build.gradle.kts (Module level) kamu punya dependency ini:
dependencies {
implementation(platform("androidx.compose:compose-bom:2024.12.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.activity:activity-compose:1.9.3")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7")
debugImplementation("androidx.compose.ui:ui-tooling")
}
Di buildFeatures, pastikan Compose di-enable:
android {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.15"
}
}
Sync Gradle, dan kamu siap mulai coding.
Di Compose, UI dibangun dari composable function. Ini adalah function biasa yang diberi anotasi @Composable. Contoh paling sederhana:
@Composable
fun Greeting(name: String) {
Text(
text = "Halo, $name!",
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
color = Color(FF2E7D32)
)
}
Untuk menampilkan function ini, kamu panggil dari setContent di Activity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Greeting("Developer")
}
}
}
}
Lihat bedanya? Nggak ada setContentView(R.layout.activity_main). Nggak ada inflate. Semua dari Kotlin.
Kalau di XML kamu kenal LinearLayout, RelativeLayout, FrameLayout - di Compose konsepnya sama tapi lebih intuitif:
Contoh layout sederhana untuk card profil:
@Composable
fun ProfileCard() {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Row(
modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
// Avatar
Box(
modifier = Modifier
.size(60.dp)
.clip(CircleShape)
.background(Color(FF4CAF50)),
contentAlignment = Alignment.Center
) {
Text("JD", color = Color.White, fontWeight = FontWeight.Bold)
}
Spacer(modifier = Modifier.width(16.dp))
// Info
Column {
Text("John Doe", fontSize = 18.sp, fontWeight = FontWeight.SemiBold)
Text("Android Developer", fontSize = 14.sp, color = Color.Gray)
Text("Jakarta, Indonesia", fontSize = 12.sp, color = Color.LightGray)
}
}
}
}
Perhatikan bagaimana Modifier digunakan di mana-mana. Modifier adalah cara Compose mengatur behavior dan appearance - padding, size, click, background, semuanya lewat Modifier chain.
Ini bagian yang paling powerful. Di Compose, UI otomatis update ketika state berubah. Nggak perlu notifyDataSetChanged() atau setText() manual.
@Composable
fun Counter() {
var count by remember { mutableIntStateOf(0) }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Kamu sudah klik $count kali",
fontSize = 24.sp
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { count++ }) {
Text("Tambah")
}
if (count > 10) {
Text(
text = "Wah, rajin banget nge-klik! ",
color = Color(FFFF9800),
modifier = Modifier.padding(top = 8.dp)
)
}
}
}
remember menyimpan state di dalam composable. mutableIntStateOf membuat state yang bisa berubah. Setiap kali count berubah, Compose otomatis re-compose (re-render) bagian UI yang pakai count.
Ini berbeda dari cara lama di mana kamu harus manual update setiap view. Di Compose, kamu ubah data, UI menyesuaikan sendiri. Paradigm shift yang bikin development jauh lebih cepat.
Untuk berpindah antar screen, Compose punya NavHost. Setup-nya begini:
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") {
HomeScreen(
onNavigateToDetail = { id ->
navController.navigate("detail/$id")
}
)
}
composable(
"detail/{itemId}",
arguments = listOf(navArgument("itemId") { type = NavType.IntType })
) { backStackEntry ->
val itemId = backStackEntry.arguments?.getInt("itemId") ?: 0
DetailScreen(
itemId = itemId,
onBack = { navController.popBackStack() }
)
}
}
}
Navigation di Compose type-safe dan deklaratif. Kamu define semua route di satu tempat, passing data lewat argument, dan Compose handle back stack secara otomatis.
Buat nampilin list data, Compose punya LazyColumn (vertical) dan LazyRow (horizontal). Ini pengganti RecyclerView:
@Composable
fun ArticleList(articles: List<Article>) {
LazyColumn(
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
items(
items = articles,
key = { it.id }
) { article ->
ArticleCard(article)
}
}
}
@Composable
fun ArticleCard(article: Article) {
Card(
modifier = Modifier
.fillMaxWidth()
.clickable { /* navigate to detail */ }
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(article.title, fontWeight = FontWeight.Bold, fontSize = 16.sp)
Spacer(modifier = Modifier.height(4.dp))
Text(article.category, color = Color(FF4CAF50), fontSize = 12.sp)
Spacer(modifier = Modifier.height(8.dp))
Text(
article.excerpt,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
color = Color.Gray
)
}
}
}
Nggak perlu Adapter, ViewHolder, atau DiffUtil. LazyColumn handle semuanya secara otomatis. Key parameter membantu Compose mengoptimasi recomposition.
@Preview di atas composable buat lihat preview real-time di Android Studio tanpa run emulator. Game changer buat iterasi UI.Modifier.padding(16.dp).background(Color.Red) beda hasilnya dari Modifier.background(Color.Red).padding(16.dp). Yang pertama: padding di luar background. Yang kedua: padding di dalam background.remember. Kalau nggak, object dibuat ulang setiap recomposition.MaterialTheme. Ini memastikan warna, tipografi, dan shape konsisten di semua screen.Jetpack Compose benar-benar mengubah cara saya bikin UI Android. Dari yang dulunya bolak-balik XML-Kotlin, sekarang semua di satu tempat. Code lebih sedikit, lebih readable, dan development time jauh lebih cepat.
Kalau kamu masih pakai XML, nggak ada salahnya mulai coba Compose di project baru. Mulai dari yang sederhana - satu screen, beberapa composable, sedikit state. Nanti pelan-pelan naik ke yang lebih kompleks. Trust me, once you go Compose, you won't go back.
Ada pertanyaan atau pengalaman pakai Compose? Share di kolom komentar ya!'