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 inti Compose versi 1.11 (lihat pemetaan BOM lengkap), alat debug elemen bersama, peristiwa trackpad, dan lainnya. Kami juga memiliki beberapa API eksperimental yang ingin Anda coba dan berikan masukan kepada kami.

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

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

Perubahan di Compose 1.11.0

Eksekusi coroutine dalam pengujian

Kami memperkenalkan update besar pada cara Compose menangani waktu pengujian. Setelah periode keikutsertaan yang diumumkan di Compose 1.10, API pengujian v2 kini menjadi default, dan API v1 telah dihentikan. Perubahan utamanya adalah perubahan pada dispatcher pengujian default. Meskipun API v1 mengandalkan UnconfinedTestDispatcher, yang menjalankan coroutine secara langsung, API v2 menggunakan StandardTestDispatcher. Artinya, saat coroutine diluncurkan dalam pengujian Anda, coroutine tersebut kini dimasukkan ke dalam antrean dan tidak dijalankan hingga jam virtual dimajukan.

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

Untuk memastikan pengujian Anda selaras dengan perilaku coroutine standar dan menghindari masalah kompatibilitas di 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 debugging yang berguna untuk elemen bersama dan Modifier.animatedBounds. Kini 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 Anda 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 harapan pengguna. Sebelumnya, peristiwa trackpad ini diinterpretasikan sebagai jari layar sentuh palsu dari PointerType.Touch, yang menyebabkan pengalaman pengguna yang 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 seperti yang dikenali oleh platform sejak API 34, termasuk geser dua jari dan cubit. Gestur ini dikenali secara otomatis oleh komponen seperti Modifier.scrollable dan Modifier.transformable agar memiliki perilaku yang lebih baik dengan trackpad.

Perubahan ini meningkatkan perilaku untuk trackpad di seluruh komponen bawaan, dengan touch slop yang berlebihan dihapus, gestur awal drag-and-drop yang lebih intuitif, pemilihan klik dua kali dan klik tiga kali di kolom teks, serta menu konteks bergaya 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 stylus, 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 pohon komposisi, penulis library dapat menggunakan compositionLocalWithHostDefaultOf untuk membuat CompositionLocal yang menyelesaikan default dari host.

Wrapper pratinjau

Pratinjau kustom Android Studio adalah fitur baru yang memungkinkan Anda menentukan dengan tepat 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 ini 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 mengurangi kode berulang secara signifikan.

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 dan penghapusan

  • Seperti yang diumumkan di postingan blog Compose 1.10, kami menghentikan Modifier.onFirstVisible(). Namanya sering kali menyebabkan kesalahpahaman, terutama dalam tata letak lambat, yang akan dipicu beberapa kali selama scrolling. Sebaiknya migrasikan ke Modifier.onVisibilityChanged(), yang memungkinkan pelacakan manual status visibilitas yang lebih akurat 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 diberikan. Fokus dapat dipindahkan ke elemen lain hanya jika kursor mencapai akhir teks.

API mendatang

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 akan mewarisi persyaratan ini. Sebaiknya selalu gunakan versi terbaru yang dirilis, karena Compose bertujuan untuk segera mengadopsi compileSdks baru untuk memberikan akses ke fitur Android terbaru. Pastikan untuk melihat dokumentasi di sini untuk mengetahui informasi selengkapnya tentang versi AGP yang didukung untuk berbagai tingkat API. 

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

Gaya (Eksperimental)

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

Contoh dasar penggantian latar belakang gaya status yang 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 menyediakan cara deklaratif dan berperforma tinggi untuk menyesuaikan UI Anda dengan lingkungannya. API ini mengabstraksi pengambilan informasi yang kompleks menjadi kondisi sederhana dalam UiMediaScope, sehingga memastikan rekomposisi hanya terjadi jika diperlukan.

Dengan dukungan untuk berbagai sinyal lingkungan—mulai dari kemampuan perangkat seperti jenis keyboard dan presisi pointer, hingga status kontekstual seperti ukuran dan postur jendela—Anda dapat membangun pengalaman yang sangat responsif. Performa disertakan dengan derivedMediaQuery untuk menangani update frekuensi tinggi, sementara kemampuan untuk mengganti cakupan membuat pengujian dan pratinjau menjadi lancar di seluruh konfigurasi hardware. Sebelumnya, untuk mendapatkan akses ke properti perangkat tertentu—seperti jika perangkat berada dalam mode di atas meja —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 berada 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 membangun tata letak dua dimensi yang kompleks di Jetpack Compose. Meskipun Row dan Column sangat bagus untuk desain linear, Grid memberi Anda kontrol struktural yang diperlukan untuk arsitektur tingkat layar dan komponen yang rumit tanpa overhead daftar yang dapat di-scroll. Grid memungkinkan Anda menentukan tata letak menggunakan jalur, celah, dan sel, yang menawarkan opsi ukuran yang familiar 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 menjangkau item di beberapa baris dan kolom untuk presisi. Yang terbaik dari semuanya, API ini sangat adaptif—Anda dapat mengonfigurasi ulang jalur dan rentang petak secara dinamis untuk merespons status perangkat seperti mode di atas meja atau perubahan orientasi, sehingga memastikan UI Anda terlihat bagus di seluruh faktor bentuk.

Grid.gif

Lihat dokumentasi dan laporkan bug di sini

FlexBox (Eksperimental)

FlexBox adalah penampung tata letak yang dirancang untuk UI adaptif berperforma tinggi. Fitur ini mengelola ukuran item dan distribusi ruang berdasarkan dimensi penampung yang tersedia.Fitur ini menangani tugas kompleks seperti wrapping (wrap) dan perataan multi-sumbu item (justifyContent, alignItems, alignContent). Fitur 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. Implementasi baru ini dirancang untuk meningkatkan performa, terutama terkait pengeditan acak.

Untuk mencoba SlotTable baru, aktifkan ComposeRuntimeFlags.isLinkBufferComposerEnabled

Mulai coding hari ini

Dengan banyaknya API baru yang menarik di Jetpack Compose, dan masih 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 tahap pengembangan) — harap laporkan di sini. Selamat belajar menulis kode!

Ditulis oleh:

Lanjutkan membaca