Modifier — rantai pengubah dan performa di Compose

Penulis: IT Sectr Diterbitkan: 2026-06-28 Waktu membaca: 8 mnt

Modifier — adalah objek yang tidak dapat diubah di Jetpack Compose yang menentukan properti komponen UI: ukuran, margin, latar belakang, pemrosesan gestur, dan perilaku. Pengubah digabungkan dalam rantai melalui pemanggilan berurutan, di mana urutan penerapannya secara kritis memengaruhi hasil. Menurut Google Android Developers, 2026, penggunaan Modifier yang benar adalah dasar membangun antarmuka yang fleksibel dan berperforma tinggi di UI deklaratif.

Poin Utama

  • Modifier — objek tidak berubah yang mendeskripsikan tampilan dan perilaku komponen UI
  • Rantai pengubah dibangun secara berurutan, urutan memengaruhi tampilan
  • Urutan penting: padding → size berbeda dengan size → padding
  • Modifier.composed memungkinkan pembuatan pengubah komposit kustom
  • Optimasi: hindari pembuatan ulang Modifier pada setiap rekomposisi

Apa itu Modifier di Jetpack Compose

Modifier — adalah antarmuka dari paket androidx.compose.ui yang mengimplementasikan pola Composite. Setiap pengubah adalah elemen rantai yang membungkus yang sebelumnya dan menambahkan perilakunya sendiri. Modifier bersifat tidak berubah — setiap perubahan menciptakan objek baru melalui penyalinan dengan penambahan elemen baru ke rantai. Ini memungkinkan berbagi satu Modifier secara aman di antara banyak komponen.

Fungsi-fungsi pengubah dasar dipanggil melalui objek pendamping Modifier (misalnya, Modifier.padding(), Modifier.fillMaxWidth()). Setiap fungsi mengembalikan Modifier baru dengan elemen yang ditambahkan. Jika ada beberapa pengubah, mereka digabungkan dalam rantai: Modifier.padding(16.dp).fillMaxWidth().background(Color.Blue). Urutan adalah arah dari luar ke dalam relatif terhadap elemen UI.

Tidak seperti View tradisional, di mana properti diatur melalui setter (view.setPadding(...), view.setBackground(...)), di Compose Modifier adalah deskripsi deklaratif. Komponen tidak "menerapkan" pengubah selama eksekusi — LayoutNode pada fase komposisi melintasi rantai Modifier dan mengumpulkan daftar Modifier.Element, yang kemudian diproses pada fase pengukuran dan penataan.

Rantai pengubah dan urutan penerapan

Urutan pengubah — salah satu kesalahan paling umum di Compose. Setiap pengubah membungkus yang sebelumnya, dan operasi dijalankan dari luar ke dalam. Misalnya, padding(16.dp).clickable { }: pertama margin ditambahkan di sekitar elemen, kemudian area klik mencakup juga margin. clickable { }.padding(16.dp): pertama area klik sama dengan ukuran elemen, kemudian margin ditambahkan di sekelilingnya — klik pada margin tidak akan berfungsi.

Aturan mengingat: baca rantai dari kiri ke kanan dan terapkan dari luar ke dalam. Pengubah pertama — yang paling luar, diterapkan pada area di sekitar elemen. Pengubah terakhir — yang paling dalam, diterapkan langsung ke konten. Pengubah ukuran (size, fillMaxWidth) harus mengikuti margin, jika margin diperlukan dari induk, atau sebelum margin, jika konten harus dibatasi terlebih dahulu, kemudian dipusatkan.

Contoh: size(100.dp).padding(10.dp) — elemen ukuran tetap 100dp, kemudian padding 10dp di luar (ukuran akhir 120dp). padding(10.dp).size(100.dp) — padding 10dp mengurangi ruang yang tersedia menjadi (induk - 20dp), kemudian size(100dp) dapat melampaui induk. Selalu pikirkan urutan secara sadar, menggunakan tes tampilan untuk memverifikasi hasil.

UrutanHasil
padding → clickableKlik berfungsi juga di area margin
clickable → paddingKlik hanya berfungsi pada konten, margin adalah zona mati
size → paddingElemen size(100), padding di luar → 100+2*pad
padding → sizepadding mengurangi ruang, size dapat melampaui batas
background → paddingLatar belakang mengisi seluruh elemen termasuk area luar
padding → backgroundLatar belakang hanya di dalam margin (area luar transparan)

Jenis pengubah: ukuran, margin, dekorasi, dan perilaku

Pustaka standar Compose mencakup ~50+ pengubah, dibagi ke dalam kategori. Ukuran dan posisi: Modifier.size(), width(), height(), fillMaxSize(), fillMaxWidth(), fillMaxHeight(), defaultMinSize(), requiredSize(). Margin dan batas: padding(), offset(), margin (ditempatkan melalui padding induk atau Layout). Dekorasi: background(), border(), clip(), alpha(), shadow(), blur().

Perilaku dan gestur: clickable(), combinedClickable(), pointerInput(), draggable(), swipeable(). Penataan dalam wadah: weight() (untuk Row/Column), align(), alignBy(), matchParentSize(). Semantik dan aksesibilitas: semantics(), testTag(), clearAndSetSemantics(). Menggambar: drawBehind(), drawWithContent(), drawModifier() — pengubah yang memungkinkan penggambaran kustom di kanvas.

Pengubah semantik — kategori khusus. Modifier.semantics {} menentukan bagaimana elemen akan direpresentasikan di pohon Accessibility. Compose secara otomatis mengisi semantik dari teks, tetapi untuk komponen kustom, peran, status, dan tindakan harus ditentukan secara manual. Ini sangat penting untuk kepatuhan WCAG 2.2 dan fungsi TalkBack (Android) serta VoiceOver (iOS) yang benar.

kotlin
@Composable
fun ModifierDemo() {
    // Rantai pengubah dengan urutan yang benar
    Box(
        modifier = Modifier
            .size(150.dp)
            .padding(8.dp)
            .border(2.dp, Color.Gray)
            .background(Color(0xFFE3F2FD))
            .clickable { /* handle click */ }
            .semantics {
                contentDescription = "Demo card with click action"
                role = Role.Button
            }
    ) {
        Text("Sentuh saya")
    }
}

Membuat pengubah kustom dengan Modifier.composed

Modifier.composed — adalah metode pabrik yang memungkinkan pembuatan pengubah komposit yang dapat menggunakan pengubah lain, LocalComposition, dan status lokal. Tidak seperti fungsi ekstensi biasa, composed membuat instance setiap kali diterapkan, yang memungkinkan memiliki status sendiri di dalam pengubah.

Kapan menggunakan composed: kombinasi berulang pengubah (misalnya, gaya kartu standar: padding + background + border + clickable); pengubah dengan status (perubahan latar belakang animasi saat ditekan); akses ke CompositionLocals (skema warna MaterialTheme, kerapatan piksel). Dalam kasus biasa, fungsi ekstensi biasa tanpa composed sudah cukup.

Performa composed: setiap pemanggilan membuat objek pengubah baru, yang dapat menyebabkan alokasi berlebihan saat rekomposisi. Untuk mencegahnya, bungkus composed dalam remember. Google merekomendasikan penggunaan composed hanya ketika benar-benar membutuhkan status atau CompositionLocal di dalamnya. Untuk kombinasi statis, gunakan fungsi ekstensi biasa.

kotlin
// Pengubah kustom melalui composed dengan status
fun Modifier.cardStyle(
    elevation: Dp = 4.dp,
    isSelected: Boolean = false
): Modifier = this.composed {
    val backgroundColor = if (isSelected)
        MaterialTheme.colorScheme.primaryContainer
    else
        MaterialTheme.colorScheme.surface

    this
        .fillMaxWidth()
        .padding(12.dp)
        .background(backgroundColor, RoundedCornerShape(8.dp))
        .shadow(elevation, RoundedCornerShape(8.dp))
}

// Contoh penggunaan
@Composable
fun CardList() {
    Column {
        Box(Modifier.cardStyle()) { Text("Item 1") }
        Box(Modifier.cardStyle(isSelected = true)) { Text("Dipilih") }
    }
}

// Versi statis (tanpa composed) — lebih cepat
fun Modifier.simpleCardStyle(): Modifier =
    this.fillMaxWidth().padding(8.dp).clip(RoundedCornerShape(4.dp))

Performa Modifier dan praktik terbaik

Hindari pembuatan ulang Modifier pada setiap rekomposisi. Jika pengubah tidak bergantung pada data yang berubah — tempatkan dalam konstanta atau remember. Setiap kali Modifier.padding().background() dipanggil, objek Modifier.Element baru dibuat. Dalam komponen terisolasi, ini tidak terlihat, tetapi di LazyColumn dengan ratusan elemen, alokasi berlebihan menyebabkan kelambatan yang terlihat saat menggulir.

Aturan: jika rantai pengubah tidak bergantung pada parameter fungsi Composable — deklarasikan sebagai val di luar fungsi (di tingkat file atau Companion). Jika bergantung — gunakan remember(ketergantungan) { ... }. Untuk pengubah yang selalu sama, cara paling efisien adalah val di luar Composable: objek semacam itu dibuat sekali untuk seluruh masa pakai aplikasi.

Praktik terbaik pengurutan Modifier: tempatkan pengubah dalam urutan logis: pertama ukuran/margin (layout), kemudian dekorasi (background, border), lalu perilaku (clickable, pointerInput). Ini tidak hanya meningkatkan keterbacaan, tetapi juga membantu Compose Runtime mengoptimalkan rantai pada fase pengukuran. Juga hindari Box bersarang berlebihan dengan Modifier berbeda — seringkali satu Modifier pada wadah induk dapat menggantikan 2-3 kotak bersarang.

kotlin
// ✅ Baik: konstanta di luar Composable
private val cardModifier = Modifier
    .fillMaxWidth()
    .padding(16.dp)
    .clip(RoundedCornerShape(8.dp))

@Composable
fun CardContent() {
    Box(cardModifier.background(Color.White)) { ... }
}

// ❌ Buruk: pembuatan ulang pada setiap rekomposisi
@Composable
fun BadCard() {
    Box(Modifier.fillMaxWidth().padding(16.dp)) { ... }
}

// ✅ Baik: remember untuk Modifier dinamis
@Composable
fun DynamicCard(color: Color) {
    val modifier = remember(color) {
        Modifier.fillMaxWidth().background(color)
    }
    Box(modifier) { ... }
}

Pertanyaan yang Sering Diajukan

Bisakah satu Modifier digunakan untuk beberapa Composable?

Ya, Modifier tidak dapat diubah, jadi satu objek dapat digunakan dengan aman di beberapa tempat. Namun, jika Anda menggunakan composed-modifier, setiap pemanggilan membuat instance baru. Untuk rantai statis, konstanta atau val di luar Composable adalah solusi optimal.

Bagaimana cara men-debug rantai pengubah?

Gunakan Layout Inspector di Android Studio — ia secara visual menunjukkan batas setiap Modifier. Untuk debugging terprogram, tambahkan Modifier.border() dengan warna berbeda di setiap langkah rantai untuk melihat batas penerapan setiap pengubah.

Apa itu Modifier.then() dan apa bedanya dengan pemanggilan berurutan?

Modifier.then(other) menggabungkan rantai other ke this. Pemanggilan berurutan (Modifier.a().b()) setara dengan Modifier.then(a()).then(b()). Tidak ada perbedaan — ini adalah mekanisme rantai yang sama. then() berguna ketika Anda perlu menggabungkan rantai yang sudah jadi dari sebuah variabel.

Bagaimana Modifier memengaruhi semantik Aksesibilitas?

Modifier.semantics {} menentukan bagaimana elemen akan dideskripsikan untuk pembaca layar. Modifier.clickable() secara otomatis menambahkan peran Button dan Action(OnClick). Untuk gestur kustom, Anda harus menentukan semantics secara eksplisit. Tanpa pengubah semantik, pengguna TalkBack tidak akan dapat berinteraksi dengan komponen kustom.

Mengapa background di Modifier tidak berfungsi dengan sudut membulat?

Modifier.background(color, shape) berfungsi dengan sudut, tetapi clip() harus SEBELUM background agar sudut terpotong. Urutan yang benar: clip(shape).background(color). Jika Anda perlu memotong juga konten di dalamnya, gunakan clipToBounds() pada induk.

Kesimpulan

  • Modifier — objek tidak berubah untuk deskripsi deklaratif tampilan dan perilaku
  • Urutan pengubah menentukan hasil: padding → clickable vs clickable → padding
  • Rantai dibangun secara berurutan, setiap elemen membungkus yang sebelumnya
  • Modifier.composed memungkinkan pembuatan pengubah dengan status dan CompositionLocal
  • Performa: tempatkan rantai statis dalam konstanta, gunakan remember untuk yang dinamis
  • Semantik: Modifier.semantics wajib untuk Aksesibilitas komponen kustom
  • Rekomendasi: tempatkan pengubah dari layout ke dekorasi, lalu ke perilaku

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga