Mengelompokkan target fokus

Anda dapat mengelompokkan beberapa target fokus menggunakan pengubah focusGroup. Pengelompokan memungkinkan Anda mengelola hierarki fokus, mengisolasi region UI logis (seperti toolbar, tindakan dialog, atau daftar kartu), dan mencegat saat fokus masuk atau keluar dari region.

Konsep grup fokus: masuk, keluar, dan traversal default

Grup fokus membuat batas navigasi yang kohesif di sekitar target fokus turunannya. Memahami cara fokus berpindah melintasi batas ini bergantung pada dua konsep utama:

  • Enter: Peristiwa yang terjadi saat fokus beralih dari elemen apa pun di luar grup fokus ke elemen di dalam grup.
  • Keluar: Peristiwa yang terjadi saat fokus keluar dari elemen internal terakhir grup dan beralih ke target fokus eksternal.
Diagram yang menunjukkan transisi Masuk dan Keluar di seluruh batas grup fokus.
Gambar 1. Grup fokus dengan peristiwa masuk dan keluar.

Perilaku traversal fokus default

Secara default, saat grup fokus menerima fokus dari luar:

  1. Memasuki grup: Compose otomatis memilih target fokus turunan internal. Untuk navigasi satu dimensi (Tab), navigasi ini memilih turunan pertama dalam urutan tampilan visual. Untuk navigasi dua dimensi (tombol panah atau D-pad), navigasi ini memilih turunan yang secara geometris paling dekat dengan arah masuk.
  2. Menavigasi dalam grup: Penekanan tombol navigasi berulang kali akan memindahkan fokus di antara target fokus yang setara yang disertakan oleh grup.
  3. Keluar dari grup: Setelah pengguna menavigasi melewati target fokus terakhir di dalam grup, penekanan tombol berikutnya akan keluar dari grup dan memindahkan fokus ke target fokus di sekitarnya di luar grup.

Menyesuaikan pengalihan entri fokus

Dalam banyak desain UI, target entri default (seperti turunan pertama dalam urutan tampilan) bukanlah pilihan yang paling logis atau praktis bagi pengguna.

Tujuan dan kasus penggunaan

Pertimbangkan dialog konfirmasi dengan tombol "Batal" di sebelah kiri dan tombol "Konfirmasi" utama di sebelah kanan. Saat pengguna menavigasi ke bawah ke panel tombol dari kolom formulir:

  • Perilaku default: Fokus akan mendarat di "Batal" karena merupakan tombol pertama dalam urutan tampilan visual.
  • Perilaku yang diinginkan: Karena "Konfirmasi" adalah tindakan utama yang direkomendasikan, Anda mungkin ingin fokus langsung mendarat di "Konfirmasi" saat memasuki grup tombol dari urutan fokus sebelumnya, sambil tetap mengizinkan pengguna menekan Kiri untuk memilih "Batal" jika diperlukan.
Entri fokus default ke dalam grup tombol.
Gambar 2. Tombol Cancel dan Confirm dengan target entri fokus default.

Kasus penggunaan umum lainnya mencakup:

  • Memindahkan fokus langsung ke tab yang saat ini dipilih saat memasuki TabRow.
  • Memindahkan fokus langsung ke kontrol "Putar / Jeda" saat memasuki panel pemutaran media.

Implementasi dengan onEnter dan FocusRequester

Untuk mengalihkan fokus saat memasuki grup fokus:

  1. Terapkan pengubah focusGroup ke penampung induk yang menyertakan target fokus terkait.
  2. Terapkan pengubah focusProperties ke penampung, dan konfigurasikan callback onEnter.
  3. Dalam callback onEnter (mencakup FocusEnterExitScope), panggil requestFocus() di FocusRequester yang terkait dengan turunan default pilihan menggunakan focusRequester.

val defaultChildRequester = remember { FocusRequester() }

Row(
    modifier = Modifier
        .focusGroup()
        .focusProperties {
            // Intercept entry into this group and redirect focus to the primary action
            onEnter = {
                defaultChildRequester.requestFocus()
            }
        }
) {
    Button(onClick = { /* Cancel action */ }) {
        Text("Cancel")
    }
    Button(
        onClick = { /* Confirm action */ },
        modifier = Modifier.focusRequester(defaultChildRequester)
    ) {
        Text("Confirm (Default)")
    }
}

Di dalam onEnter dan onExit, Anda juga dapat memanggil cancelFocusChange() untuk memblokir sepenuhnya transisi fokus di seluruh batas, atau memeriksa requestedFocusDirection untuk menyesuaikan pemilihan rute berdasarkan apakah pengguna melakukan navigasi menggunakan Tab, Bawah, atau Kiri.

Penampung yang dapat di-scroll adalah grup fokus secara default

Di Jetpack Compose, penampung yang dapat di-scroll seperti LazyRow, LazyColumn, dan LazyVerticalGrid otomatis bertindak sebagai grup fokus. Anda tidak perlu menerapkan pengubah focusGroup secara eksplisit ke pengubah tersebut untuk menyetel callback onEnter atau onExit.