Secara default, perilaku pembaca layar aksesibilitas di aplikasi Compose diterapkan
dalam urutan membaca yang diharapkan, yang biasanya dari kiri ke kanan, lalu dari atas ke bawah.
Namun, ada beberapa jenis tata letak aplikasi yang tidak dapat ditentukan oleh algoritma
urutan pembacaan yang sebenarnya
tanpa petunjuk tambahan. Di aplikasi berbasis tampilan, Anda dapat
memperbaiki masalah tersebut menggunakan properti traversalBefore
dan traversalAfter
.
Mulai Compose 1.5, Compose menyediakan API yang sama fleksibelnya, tetapi dengan
sebuah model konseptual yang baru.
isTraversalGroup
dan traversalIndex
adalah properti semantik yang
memungkinkan Anda mengontrol aksesibilitas dan urutan fokus TalkBack dalam skenario
algoritma penyortiran secara
default adalah tidak sesuai. isTraversalGroup
mengidentifikasi
grup penting secara semantik, sedangkan traversalIndex
menyesuaikan urutan
elemen individu dalam
kelompok-kelompok tersebut. Anda hanya dapat menggunakan isTraversalGroup
,
atau dengan traversalIndex
untuk penyesuaian lebih lanjut.
Gunakan isTraversalGroup
dan traversalIndex
di
aplikasi untuk mengontrol urutan traversal pembaca layar.
Mengelompokkan elemen dengan isTraversalGroup
isTraversalGroup
adalah properti boolean yang menentukan apakah semantik
node adalah grup traversal. Jenis {i>node<i} ini adalah {i>node<i} yang
fungsinya akan melayani
sebagai pembatas atau pembatas dalam
mengatur turunan node.
Menetapkan isTraversalGroup = true
pada node berarti bahwa semua turunan dari node tersebut
dikunjungi sebelum pindah ke elemen lain. Anda dapat menyetel isTraversalGroup
di
node yang dapat difokuskan pembaca non-layar, seperti Kolom, Baris, atau Kotak.
Contoh berikut menggunakan isTraversalGroup
. Kode ini memancarkan empat elemen teks. Tujuan
dua elemen kiri adalah milik satu elemen CardBox
, sedangkan dua elemen kanan
termasuk dalam elemen CardBox
lain:
// CardBox() function takes in top and bottom sample text. @Composable fun CardBox( topSampleText: String, bottomSampleText: String, modifier: Modifier = Modifier ) { Box(modifier) { Column { Text(topSampleText) Text(bottomSampleText) } } } @Composable fun TraversalGroupDemo() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is " val bottomSampleText2 = "on the right." Row { CardBox( topSampleText1, bottomSampleText1 ) CardBox( topSampleText2, bottomSampleText2 ) } }
Kode ini menghasilkan output yang mirip dengan berikut ini:
Karena tidak ada semantik yang ditetapkan, perilaku default pembaca layar adalah untuk melintasi elemen dari kiri ke kanan dan atas ke bawah. Karena ini Secara default, TalkBack membacakan fragmen kalimat dalam urutan yang salah:
"Kalimat ini dalam" → "Kalimat ini" → "kolom kiri". → "di benar."
Untuk mengurutkan fragmen dengan benar, ubah cuplikan asli untuk menetapkan
isTraversalGroup
ke true
:
@Composable fun TraversalGroupDemo2() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is" val bottomSampleText2 = "on the right." Row { CardBox( // 1, topSampleText1, bottomSampleText1, Modifier.semantics { isTraversalGroup = true } ) CardBox( // 2, topSampleText2, bottomSampleText2, Modifier.semantics { isTraversalGroup = true } ) } }
Karena isTraversalGroup
ditetapkan secara khusus pada setiap CardBox
, CardBox
batas-batas berlaku saat
menyortir elemen-elemennya. Dalam hal ini, kolom kiri
CardBox
dibaca terlebih dahulu, diikuti dengan CardBox
yang tepat.
Kini, TalkBack membacakan fragmen kalimat dalam urutan yang benar:
"Kalimat ini dalam" → "kolom kiri". → "Kalimat ini" → "di benar."
Sesuaikan urutan traversal lebih lanjut
traversalIndex
adalah properti float yang memungkinkan Anda menyesuaikan TalkBack
urutan lintasan. Jika mengelompokkan elemen bersama-sama tidak cukup bagi TalkBack untuk
berfungsi dengan benar, gunakan traversalIndex
bersama
isTraversalGroup
untuk menyesuaikan pengurutan pembaca layar lebih lanjut.
Properti traversalIndex
memiliki karakteristik berikut:
- Elemen dengan nilai
traversalIndex
yang lebih rendah akan diprioritaskan terlebih dahulu. - Bisa positif atau negatif.
- Nilai default-nya adalah
0f
. - Hanya memengaruhi node yang dapat difokuskan pembaca layar, seperti elemen di layar seperti
teks atau tombol. Misalnya, menetapkan hanya
traversalIndex
pada kolom akan tidak berpengaruh, kecuali jika kolom memilikiisTraversalGroup
yang ditetapkan di dalamnya.
Contoh berikut menunjukkan cara menggunakan traversalIndex
dan
isTraversalGroup
bersama-sama.
Contoh: Tampilan jam Traverse
Tampilan jam adalah skenario umum di mana urutan traversal standar tidak Anda. Contoh di bagian ini adalah pemilih waktu, di mana pengguna dapat melewati melihat angka pada tampilan jam dan pilih digit untuk jam dan menit slot waktu.
Dalam cuplikan yang disederhanakan berikut, terdapat CircularLayout
dengan 12
angka akan digambar, dimulai dengan 12 dan bergerak searah jarum jam di sekitar lingkaran:
@Composable fun ClockFaceDemo() { CircularLayout { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier) { Text((if (value == 0) 12 else value).toString()) } }
Karena tampilan jam tidak dibaca secara logis dengan default{i> <i}kiri-ke-kanan dan dengan pengurutan dari atas ke bawah, TalkBack membacakan angka secara tidak berurutan. Untuk meralat gunakan nilai penghitung yang bertambah, seperti ditunjukkan dalam cuplikan berikut:
@Composable fun ClockFaceDemo() { CircularLayout(Modifier.semantics { isTraversalGroup = true }) { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) { Text((if (value == 0) 12 else value).toString()) } }
Untuk menetapkan pengurutan traversal dengan benar, pertama-tama buat CircularLayout
sebagai
traversal group dan setel isTraversalGroup = true
. Kemudian, karena setiap teks jam
digambar ke tata letak, tetapkan traversalIndex
yang sesuai ke penghitung
dengan sejumlah nilai.
Karena nilai hitungan terus meningkat, nilai
traversalIndex
lebih besar saat angka ditambahkan ke layar—nilai jam 0
memiliki traversalIndex
0, dan nilai jam 1 memiliki traversalIndex
1.
Dengan cara ini, urutan pembacaan TalkBack akan diatur. Sekarang, angka
di dalam CircularLayout
dibaca sesuai urutan yang diharapkan.
Karena traversalIndexes
yang telah ditetapkan hanya berhubungan dengan
indeks dalam pengelompokan yang sama, urutan layar lainnya telah
dipertahankan. Dengan kata lain, perubahan semantik yang ditunjukkan dalam kode sebelumnya
hanya mengubah urutan dalam tampilan jam yang memiliki
isTraversalGroup = true
disetel.
Perlu diketahui bahwa tanpa menetapkan semantik CircularLayout's
ke isTraversalGroup =
true
, perubahan traversalIndex
tetap berlaku. Namun, tanpa
CircularLayout
untuk mengikatnya, dua belas digit tampilan jam akan dibaca
terakhir, setelah semua elemen
lain di layar dikunjungi. Hal ini terjadi
karena semua elemen lainnya memiliki traversalIndex
default 0f
, dan
elemen teks jam dibaca setelah semua elemen 0f
lainnya.
Contoh: Menyesuaikan urutan traversal untuk tombol tindakan mengambang
Dalam contoh ini, traversalIndex
dan isTraversalGroup
mengontrol
pengurutan traversal tombol tindakan mengambang (FAB) Desain Material. Dasar
dari contoh ini adalah tata letak berikut:
Secara default, tata letak dalam contoh ini memiliki urutan TalkBack berikut:
Panel Aplikasi Atas → Contoh teks 0 sampai 6 → tombol tindakan mengambang (FAB) → Bawah Panel Aplikasi
Anda mungkin ingin pembaca layar fokus terlebih dahulu pada FAB. Untuk menyetel
traversalIndex
pada elemen Material seperti FAB, lakukan hal berikut:
@Composable fun FloatingBox() { Box(modifier = Modifier.semantics { isTraversalGroup = true; traversalIndex = -1f }) { FloatingActionButton(onClick = {}) { Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon") } } }
Dalam cuplikan ini, membuat kotak dengan
isTraversalGroup
ditetapkan ke true
dan menyetel traversalIndex
di kotak yang sama
(-1f
lebih rendah dari nilai default 0f
) berarti kotak mengambang
ditempatkan sebelum semua elemen lain di layar.
Selanjutnya, Anda dapat meletakkan kotak mengambang dan elemen lainnya ke dalam perancah, yang mengimplementasikan tata letak Desain Material:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ColumnWithFABFirstDemo() { Scaffold( topBar = { TopAppBar(title = { Text("Top App Bar") }) }, floatingActionButtonPosition = FabPosition.End, floatingActionButton = { FloatingBox() }, content = { padding -> ContentColumn(padding = padding) }, bottomBar = { BottomAppBar { Text("Bottom App Bar") } } ) }
TalkBack berinteraksi dengan elemen dalam urutan berikut:
FAB → Panel Aplikasi Atas → Teks contoh 0 sampai 6 → Panel Aplikasi Bawah
Referensi lainnya
- Aksesibilitas: Konsep dan teknik yang umum untuk semua pengembangan aplikasi Android
- Membuat Aplikasi yang Dapat Diakses: Langkah-langkah penting yang dapat dilakukan untuk membuat aplikasi Anda lebih mudah diakses
- Prinsip-prinsip untuk meningkatkan kualitas aplikasi aksesibilitas: Prinsip utama untuk perlu diingat saat berupaya membuat aplikasi Anda lebih mudah diakses
- Menguji Aksesibilitas: Prinsip dan alat pengujian untuk aksesibilitas Android