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 memasuki atau keluar dari suatu region.

Konsep grup fokus: masuk, keluar, dan traversal default

Grup fokus menetapkan 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 transisi fokus dari elemen di luar grup fokus ke elemen di dalam grup.
  • Keluar: Peristiwa yang terjadi saat fokus keluar dari elemen internal terakhir grup dan bertransisi 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), tombol ini memilih turunan pertama dalam urutan tampilan visual. Untuk navigasi dua dimensi (tombol panah atau D-pad), anak yang dipilih adalah yang paling dekat secara geometris dengan arah yang masuk.
  2. Bernavigasi dalam grup: Penekanan tombol navigasi berulang kali akan memindahkan fokus di antara target fokus saudara 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 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 nyaman bagi pengguna.

Maksud 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 tombol ini adalah tombol pertama dalam urutan tampilan visual.
  • Perilaku yang diinginkan: Karena "Konfirmasi" adalah tindakan utama yang direkomendasikan, Anda mungkin ingin fokus mendarat langsung di "Konfirmasi" saat memasuki grup tombol dari sebelumnya dalam urutan fokus, sambil tetap memungkinkan pengguna menekan Kiri untuk memilih "Batal" jika diperlukan.
Entri fokus default ke dalam grup tombol.
Gambar 2. Tombol Batal dan Konfirmasi dengan target entri fokus default.

Kasus penggunaan umum lainnya meliputi:

  • 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 konfigurasi callback onEnter.
  3. Di callback onEnter (bercakupan FocusEnterExitScope), panggil requestFocus() pada 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 transisi fokus sepenuhnya di seluruh batas, atau memeriksa requestedFocusDirection untuk menyesuaikan perutean berdasarkan apakah pengguna berpindah 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 untuk menetapkan callback onEnter atau onExit.