Berita Produk

Yang baru di rilis Jetpack Compose April '26

Waktu baca: 5 menit
Meghan Mehta
Advokat Developer, Android

Hari ini, rilis Jetpack Compose April '26 sudah stabil. Rilis ini berisi modul Compose inti versi 1.11 (lihat pemetaan BOM lengkap), alat debug elemen bersama, peristiwa trackpad, dan lainnya. Kami juga memiliki beberapa API eksperimental yang ingin kami minta Anda coba dan berikan masukan kepada kami.

Untuk menggunakan rilis hari ini, upgrade versi BOM Compose Anda ke:

implementation(platform("androidx.compose:compose-bom:2026.04.01"))

Perubahan di Compose 1.11.0

Eksekusi coroutine dalam pengujian

Kami memperkenalkan pembaruan besar pada cara Compose menangani pengaturan waktu pengujian. Setelah periode keikutsertaan yang diumumkan di Compose 1.10, API pengujian v2 kini menjadi default, dan API v1 telah dihentikan. Perubahan utama adalah peralihan di dispatcher pengujian default. Meskipun API v1 mengandalkan UnconfinedTestDispatcher, yang langsung mengeksekusi rutin, API v2 menggunakan StandardTestDispatcher. Artinya, saat coroutine diluncurkan dalam pengujian Anda, coroutine tersebut kini diantrekan dan tidak dieksekusi hingga jam virtual dimajukan.

Hal ini lebih meniru kondisi produksi, secara efektif menghilangkan kondisi persaingan dan membuat rangkaian pengujian Anda jauh lebih andal dan tidak mudah gagal.

Untuk memastikan pengujian Anda selaras dengan perilaku rutin standar dan untuk menghindari masalah kompatibilitas pada masa mendatang, sebaiknya migrasikan rangkaian pengujian Anda. Lihat panduan migrasi komprehensif kami untuk pemetaan API dan perbaikan umum.

Peningkatan elemen bersama dan alat animasi

Kami juga telah menambahkan beberapa alat visual yang berguna untuk men-debug elemen bersama dan Modifier.animatedBounds. Sekarang Anda dapat melihat dengan tepat apa yang terjadi di balik layar—seperti batas target, lintasan animasi, dan jumlah kecocokan yang ditemukan—sehingga lebih mudah untuk mengetahui alasan transisi mungkin tidak berperilaku seperti yang diharapkan. Untuk menggunakan alat baru, cukup sertakan SharedTransitionLayout dengan composable LookaheadAnimationVisualDebugging

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

Peristiwa trackpad

Kami telah memperbarui dukungan Compose untuk trackpad, seperti trackpad laptop bawaan, trackpad yang dapat dipasang untuk tablet, atau trackpad eksternal/virtual. Peristiwa trackpad dasar kini umumnya akan dianggap sebagai peristiwa PointerType.Mouse, yang menyelaraskan perilaku mouse dan trackpad agar lebih sesuai dengan ekspektasi pengguna. Sebelumnya, peristiwa trackpad ini ditafsirkan sebagai jari layar sentuh palsu PointerType.Touch, yang menyebabkan pengalaman pengguna membingungkan. Misalnya, mengklik dan menarik dengan trackpad akan men-scroll, bukan memilih. Dengan mengubah jenis pointer yang dimiliki peristiwa ini dalam rilis Compose terbaru, mengklik dan menarik dengan trackpad tidak akan lagi men-scroll.

Kami juga menambahkan dukungan untuk gestur trackpad yang lebih rumit yang dikenali oleh platform sejak API 34, termasuk geser dua jari dan mencubit. Gestur ini secara otomatis dikenali oleh komponen seperti Modifier.scrollable dan Modifier.transformable untuk memiliki perilaku yang lebih baik dengan trackpad.

Perubahan ini meningkatkan perilaku untuk trackpad di seluruh komponen bawaan, dengan menghilangkan kemiringan sentuh yang berlebihan, gestur memulai tarik lalu lepas yang lebih intuitif, pemilihan klik dua kali dan klik tiga kali di kolom teks, serta menu konteks gaya desktop di kolom teks.

Untuk menguji perilaku trackpad, ada API pengujian baru dengan performTrackpadInput, yang memungkinkan validasi perilaku aplikasi Anda saat digunakan dengan trackpad. Jika Anda memiliki pendeteksi gestur kustom, validasi perilaku di seluruh jenis input, termasuk layar sentuh, mouse, trackpad, dan stilus, serta pastikan dukungan untuk roda scroll mouse dan gestur trackpad.

beforeAndAfter.webp

Default host komposisi (runtime Compose)

Kami memperkenalkan HostDefaultProviderLocalHostDefaultProviderHostDefaultKey, dan ViewTreeHostDefaultKey untuk menyediakan layanan tingkat host secara langsung melalui compose-runtime. Hal ini menghilangkan kebutuhan library untuk bergantung pada compose-ui untuk pencarian, sehingga mendukung Multiplatform Kotlin dengan lebih baik. Untuk menautkan nilai ini ke hierarki komposisi, penulis library dapat menggunakan compositionLocalWithHostDefaultOf untuk membuat CompositionLocal yang menyelesaikan default dari host.

Melihat pratinjau wrapper

Pratinjau kustom Android Studio adalah fitur baru yang memungkinkan Anda menentukan secara persis cara konten pratinjau Compose ditampilkan.

Dengan menerapkan antarmuka PreviewWrapperProvider dan menerapkan anotasi @PreviewWrapper baru, Anda dapat dengan mudah menyisipkan logika kustom, seperti menerapkan Theme tertentu. Anotasi dapat diterapkan ke fungsi yang dianotasi dengan @Composable dan @Preview atau @MultiPreview, yang menawarkan solusi generik dan mudah digunakan yang berfungsi di seluruh fitur pratinjau dan secara signifikan mengurangi kode berulang.

class ThemeWrapper: PreviewWrapper {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}

@PreviewWrapperProvider(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

Penghentian penggunaan dan penghapusan

  • Seperti yang diumumkan di postingan blog Compose 1.10, kami menghentikan penggunaan Modifier.onFirstVisible(). Namanya sering kali menimbulkan kesalahpahaman, terutama dalam tata letak lambat, yang akan dipicu beberapa kali selama scrolling. Sebaiknya Anda bermigrasi ke Modifier.onVisibilityChanged(), yang memungkinkan pelacakan manual status visibilitas yang lebih presisi dan disesuaikan dengan persyaratan kasus penggunaan spesifik Anda.
  • Flag ComposeFoundationFlags.isTextFieldDpadNavigationEnabled dihapus karena navigasi D-pad untuk TextFields kini selalu diaktifkan secara default. Perilaku baru ini memastikan bahwa peristiwa D-pad dari gamepad atau remote TV pertama-tama memindahkan kursor ke arah yang ditentukan. Fokus dapat berpindah ke elemen lain hanya saat kursor mencapai akhir teks.

API yang akan datang

Dalam rilis Compose 1.12.0 mendatang, compileSdk akan diupgrade ke compileSdk 37, dengan AGP 9 dan semua aplikasi serta library yang bergantung pada Compose mewarisi persyaratan ini. Sebaiknya selalu gunakan versi terbaru yang dirilis, karena Compose berupaya segera mengadopsi compileSdks baru untuk memberikan akses ke fitur Android terbaru. Pastikan Anda membaca dokumentasi di sini untuk mengetahui informasi selengkapnya tentang versi AGP yang didukung untuk berbagai level API. 

Di Compose 1.11.0, API berikut diperkenalkan sebagai @Experimental, dan kami menantikan masukan Anda saat Anda menjelajahinya di aplikasi Anda. Perhatikan bahwa @Experimental APIs disediakan untuk evaluasi dan masukan awal serta dapat mengalami perubahan atau penghapusan signifikan dalam rilis mendatang.

Gaya (Eksperimental)

Kami memperkenalkan API dasar eksperimental baru untuk penataan gaya. Style API adalah paradigma baru untuk menyesuaikan elemen visual komponen, yang secara tradisional dilakukan dengan pengubah. Dirancang untuk memungkinkan penyesuaian yang lebih mendalam dan mudah dengan mengekspos serangkaian properti yang dapat distilisasi standar dengan gaya berbasis status sederhana dan transisi animasi. Dengan API baru ini, kami telah melihat manfaat performa yang menjanjikan. Kami berencana untuk mengadopsi Gaya dalam komponen Material setelah Style API stabil.

Contoh dasar mengganti latar belakang gaya status ditekan:

@Composable
fun LoginButton(modifier: Modifier = Modifier) {
    Button(
        onClick = {
            // Login logic
        },
        modifier = modifier,
        style = {
            background(
                Brush.linearGradient(
                    listOf(lightPurple, lightBlue)
                )
            )
            width(75.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(
                    Brush.linearGradient(
                        listOf(Color.Magenta, Color.Red)
                    )
                )
            }
        }
    ){
        Text(
            text = "Login",
        )
    }
}
styles.webp

Lihat dokumentasi dan laporkan bug di sini.

MediaQuery (Eksperimental)

API mediaQuery baru memberikan cara deklaratif dan berperforma tinggi untuk menyesuaikan UI Anda dengan lingkungannya. Hal ini mengabstraksi pengambilan informasi yang kompleks menjadi kondisi sederhana dalam UiMediaScope, sehingga memastikan rekomposisi hanya terjadi saat diperlukan.

Dengan dukungan untuk berbagai sinyal lingkungan—dari kemampuan perangkat seperti jenis keyboard dan presisi penunjuk, hingga status kontekstual seperti ukuran jendela dan postur—Anda dapat membangun pengalaman yang sangat responsif. Performa sudah terintegrasi dengan derivedMediaQuery untuk menangani update frekuensi tinggi, sementara kemampuan untuk mengganti cakupan membuat pengujian dan pratinjau lancar di seluruh konfigurasi hardware. Sebelumnya, untuk mendapatkan akses ke properti perangkat tertentu — seperti jika perangkat berada dalam mode tabletop — Anda harus menulis banyak boilerplate untuk melakukannya: 

@Composable
fun isTabletopPosture(
    context: Context = LocalContext.current
): Boolean {
    val windowLayoutInfo by
        WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsStateWithLifecycle(null)

    return windowLayoutInfo.displayFeatures.any { displayFeature ->
        displayFeature is FoldingFeature &&
            displayFeature.state == FoldingFeature.State.HALF_OPENED &&
            displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
}

@Composable
fun VideoPlayer() {
    if(isTabletopPosture()) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

Sekarang, dengan UIMediaQuery, Anda dapat menambahkan sintaksis mediaQuery untuk membuat kueri properti perangkat, seperti apakah perangkat dalam mode di atas meja:

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

Lihat dokumentasi dan laporkan bug di sini.

Petak (Eksperimental)

Grid adalah API baru yang canggih untuk membuat tata letak dua dimensi yang kompleks di Jetpack Compose. Meskipun Row dan Column sangat cocok untuk desain linear, Grid memberi Anda kontrol struktural yang diperlukan untuk arsitektur tingkat layar dan komponen rumit tanpa overhead daftar yang dapat di-scroll. Grid memungkinkan Anda menentukan tata letak menggunakan jalur, celah, dan sel, yang menawarkan opsi ukuran yang sudah dikenal seperti Dp, persentase, ukuran konten intrinsik, dan unit "Fr" yang fleksibel. 

@OptIn(ExperimentalGridApi::class)
@Composable
fun GridExample() {
    Grid(
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        Card1(modifier = Modifier.gridItem(rowSpan = 2)
        Card2(modifier = Modifier.gridItem(colmnSpan = 3)
        Card3(modifier = Modifier.gridItem(columnSpan = 2)
        Card4()
    }
}

Anda dapat menempatkan item secara otomatis atau secara eksplisit merentangkannya di beberapa baris dan kolom untuk mendapatkan presisi. Yang terbaik, tata letak ini sangat adaptif—Anda dapat mengonfigurasi ulang rentang dan jalur petak secara dinamis untuk merespons status perangkat seperti mode di atas meja atau perubahan orientasi, sehingga memastikan UI Anda terlihat bagus di berbagai faktor bentuk.

Grid.gif

Lihat dokumentasi dan laporkan bug di sini

FlexBox (Eksperimental)

FlexBox adalah penampung tata letak yang didesain untuk UI adaptif berperforma tinggi. Tata letak ini mengelola penyesuaian ukuran item dan distribusi ruang berdasarkan dimensi penampung yang tersedia.  Class ini menangani tugas kompleks seperti pembungkusan (wrap) dan perataan multi-sumbu item (justifyContent, alignItems, alignContent). Class ini memungkinkan item bertambah (grow) atau menyusut (shrink) untuk mengisi penampung. 

@OptIn(ExperimentalFlexBoxApi::class)
fun FlexBoxWrapping(){
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        RedRoundedBox()
        BlueRoundedBox()
        GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) })
        OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) })
        PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) })
    }
}
AnimationGif.gif

Lihat dokumentasi dan laporkan bug di sini.

Implementasi SlotTable baru (Eksperimental)

Kami telah memperkenalkan implementasi baru SlotTable, yang dinonaktifkan secara default dalam rilis ini. SlotTable adalah struktur data internal yang digunakan runtime Compose untuk melacak status hierarki komposisi Anda, melacak pembatalan/rekomposisi, menyimpan nilai yang diingat, dan melacak semua metadata komposisi saat runtime. Penerapan baru ini dirancang untuk meningkatkan performa, terutama terkait pengeditan acak.

Untuk mencoba SlotTable baru, aktifkan ComposeRuntimeFlags.isLinkBufferComposerEnabled

Mulai coding sekarang juga.

Dengan begitu banyak API baru yang menarik di Jetpack Compose, dan banyak lagi yang akan hadir, sekarang adalah waktu yang tepat untuk bermigrasi ke Jetpack Compose.  Seperti biasa, kami menghargai masukan dan permintaan fitur Anda (terutama pada fitur @Experimental yang masih dalam pengembangan) — ajukan di sini. Selamat menyusun!

Ditulis oleh:

Lanjutkan membaca