Menyiapkan inset jendela

Setelah Aktivitas Anda mengontrol penanganan semua inset, Anda dapat menggunakan API Compose untuk memverifikasi bahwa konten tidak terhalang dan elemen yang dapat berinteraksi tidak tumpang-tindih dengan UI sistem. API ini juga menyinkronkan tata letak aplikasi Anda dengan perubahan inset.

Menangani inset menggunakan pengubah padding atau ukuran

Misalnya, ini adalah metode paling dasar untuk menerapkan inset ke konten seluruh aplikasi Anda:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

Cuplikan ini menerapkan inset jendela safeDrawing sebagai padding di sekitar seluruh konten aplikasi. Meskipun hal ini memastikan bahwa elemen yang dapat berinteraksi tidak tumpang-tindih dengan UI sistem, hal ini juga berarti bahwa tidak ada aplikasi yang akan digambar di belakang UI sistem untuk mencapai efek layar penuh. Untuk memanfaatkan seluruh jendela sepenuhnya, Anda perlu menyesuaikan tempat inset diterapkan di setiap layar atau komponen.

Semua jenis inset ini dianimasikan secara otomatis dengan animasi IME yang di-backport ke API 21. Dengan demikian, semua tata letak yang menggunakan inset ini juga akan otomatis dianimasikan saat nilai inset berubah.

Ada tiga cara untuk menangani inset guna menyesuaikan tata letak Composable:

Pengubah padding

Modifier.windowInsetsPadding(windowInsets: WindowInsets) menerapkan inset jendela yang diberikan sebagai padding, yang bertindak seperti Modifier.padding. Misalnya, Modifier.windowInsetsPadding(WindowInsets.safeDrawing) menerapkan inset gambar yang aman sebagai padding di keempat sisi.

Ada juga beberapa metode utilitas bawaan untuk jenis inset yang paling umum. Modifier.safeDrawingPadding() adalah salah satu metode tersebut, yang setara dengan Modifier.windowInsetsPadding(WindowInsets.safeDrawing). Tabel berikut mencantumkan pengubah padding bawaan dan jenis WindowInsets yang diterapkan masing-masing:

Modifier.safeDrawingPadding()

WindowInsets.safeDrawing

Modifier.safeGesturesPadding()

WindowInsets.safeGestures

Modifier.safeContentPadding()

WindowInsets.safeContent

Modifier.statusBarsPadding()

WindowInsets.statusBars

Modifier.navigationBarsPadding()

WindowInsets.navigationBars

Modifier.captionBarPadding()

WindowInsets.captionBar

Modifier.systemBarsPadding()

WindowInsets.systemBars

Modifier.imePadding()

WindowInsets.ime

Modifier.systemGesturesPadding()

WindowInsets.systemGestures

Modifier.mandatorySystemGesturesPadding()

WindowInsets.mandatorySystemGestures

Modifier.displayCutoutPadding()

WindowInsets.displayCutout

Modifier.waterfallPadding()

WindowInsets.waterfall

Untuk mengetahui cakupan setiap jenis inset, lihat Tentang inset jendela.

Pengubah ukuran inset

Pengubah berikut menerapkan jumlah inset jendela dengan menetapkan ukuran komponen menjadi ukuran inset:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

Menerapkan sisi awal windowInsets sebagai lebar (seperti Modifier.width)

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

Menerapkan sisi akhir windowInsets sebagai lebar (seperti Modifier.width)

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

Menerapkan sisi atas windowInsets sebagai tinggi (seperti Modifier.height)

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

Menerapkan sisi bawah windowInsets sebagai tinggi (seperti Modifier.height)

Pengubah ini sangat berguna untuk mengukur Spacer yang menggunakan ruang inset:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Konsumsi inset

Pengubah padding inset (windowInsetsPadding dan helper seperti safeDrawingPadding) otomatis menggunakan bagian inset yang diterapkan sebagai padding. Saat masuk lebih dalam ke hierarki komposisi, pengubah padding inset bertingkat dan pengubah ukuran inset mengetahui bahwa sebagian inset telah digunakan oleh pengubah padding inset luar, dan menghindari penggunaan bagian inset yang sama lebih dari sekali yang akan menghasilkan terlalu banyak ruang tambahan.

Pengubah ukuran inset juga menghindari penggunaan bagian inset yang sama lebih dari sekali jika inset telah digunakan. Namun, karena mengubah ukurannya secara langsung, elemen tersebut tidak menggunakan inset itu sendiri.

Akibatnya, pengubah padding bertingkat akan otomatis mengubah jumlah padding yang diterapkan ke setiap composable.

Melihat contoh LazyColumn yang sama seperti sebelumnya, LazyColumn diubah ukurannya oleh pengubah imePadding. Di dalam LazyColumn, item terakhir diukur sesuai tinggi bagian bawah kolom sistem:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Saat IME ditutup, imePadding() tidak menerapkan padding. Akibatnya, tidak ada inset yang digunakan, dan tinggi Spacer cocok dengan kolom sistem bawah.

Saat IME terbuka, inset IME akan dianimasikan agar sesuai dengan ukuran IME, dan pengubah imePadding() akan mulai menerapkan padding bawah untuk mengubah ukuran LazyColumn saat IME terbuka. Saat pengubah imePadding() mulai menerapkan padding bawah, pengubah ini juga mulai menggunakan jumlah inset tersebut. Oleh karena itu, tinggi Spacer mulai berkurang, karena sebagian spasi untuk kolom sistem telah diterapkan oleh pengubah imePadding(). Setelah pengubah imePadding() menerapkan jumlah padding bawah yang lebih besar daripada kolom sistem, tinggi Spacer adalah nol.

Saat IME ditutup, perubahan terjadi secara terbalik: Spacer diperluas dari tinggi nol karena imePadding() menerapkan kurang dari kolom sistem bawah. Terakhir, tinggi Spacer akan cocok dengan kolom sistem setelah IME sepenuhnya dianimasikan.

Gambar 2. Kolom lambat layar penuh dengan TextField.

Perilaku ini dicapai melalui komunikasi antara semua pengubah windowInsetsPadding, dan dapat dipengaruhi dengan beberapa cara lain.

Modifier.consumeWindowInsets(insets: WindowInsets) juga menggunakan inset dengan cara yang sama seperti Modifier.windowInsetsPadding, tetapi tidak menerapkan inset yang digunakan sebagai padding. Hal ini berguna jika dikombinasikan dengan pengubah ukuran inset, untuk menunjukkan kepada elemen seinduk bahwa sejumlah inset telah digunakan:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues) berperilaku sangat mirip dengan versi yang memiliki argumen WindowInsets, tetapi menggunakan PaddingValues arbitrer untuk digunakan. Hal ini berguna untuk memberi tahu turunan saat padding atau spasi disediakan oleh beberapa mekanisme selain pengubah padding inset, seperti Modifier.padding biasa atau pengatur jarak tinggi tetap:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

Jika inset jendela mentah diperlukan tanpa penggunaan, gunakan nilai WindowInsets secara langsung, atau gunakan WindowInsets.asPaddingValues() untuk menampilkan PaddingValues inset yang tidak terpengaruh oleh penggunaan. Namun, karena peringatan berikut, sebaiknya gunakan pengubah padding inset jendela dan pengubah ukuran inset jendela jika memungkinkan.

Inset dan fase Jetpack Compose

Compose menggunakan API inti AndroidX yang mendasarinya untuk mengupdate dan menganimasikan inset, yang menggunakan API platform yang mendasarinya untuk mengelola inset. Karena perilaku platform tersebut, inset memiliki hubungan khusus dengan fase Jetpack Compose.

Nilai inset diperbarui setelah fase komposisi, tetapi sebelum fase tata letak. Artinya, pembacaan nilai inset dalam komposisi umumnya menggunakan nilai inset yang terlambat satu frame. Pengubah bawaan yang dijelaskan di halaman ini dibuat untuk menunda penggunaan nilai inset hingga fase tata letak, yang memastikan bahwa nilai inset digunakan pada frame yang sama saat diperbarui.