API Material, Compose UI, dan Foundation menerapkan dan menawarkan banyak praktik aksesibilitas secara default. Elemen ini berisi semantik bawaan yang mengikuti peran dan fungsi spesifiknya. Artinya, sebagian besar dukungan aksesibilitas disediakan dengan sedikit atau tanpa pekerjaan tambahan.
Menggunakan API yang sesuai untuk tujuan yang sesuai berarti komponen biasanya dilengkapi dengan perilaku aksesibilitas yang telah ditentukan sebelumnya yang mencakup kasus penggunaan standar. Namun, selalu periksa kembali apakah setelan default ini sesuai dengan kebutuhan aksesibilitas Anda. Jika tidak, Compose menyediakan cara untuk mencakup persyaratan yang lebih spesifik.
Memahami semantik dan pola aksesibilitas default di API Compose membantu Anda menggunakannya dengan mempertimbangkan aksesibilitas. Hal ini juga membantu Anda mendukung aksesibilitas di lebih banyak komponen kustom.
Ukuran target sentuh minimum
Elemen apa pun di layar yang dapat diklik, disentuh, atau berinteraksi dengan seseorang harus cukup besar untuk interaksi yang dapat diandalkan. Saat mengubah ukuran elemen ini, pastikan untuk menyetel ukuran minimum ke 48 dp agar dapat mengikuti panduan aksesibilitas Desain Material dengan benar.
Komponen Material—seperti Checkbox, RadioButton, Switch,
Slider, dan Surface—menetapkan ukuran minimum ini secara internal, tetapi hanya
saat komponen dapat menerima tindakan pengguna. Misalnya, jika Checkbox memiliki
parameter onCheckedChange yang disetel ke nilai non-null, kotak centang akan menyertakan
padding agar memiliki lebar dan tinggi minimal 48 dp.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }
Jika parameter onCheckedChange disetel ke null, padding tidak disertakan karena komponen tidak dapat berinteraksi secara langsung.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }
Saat menerapkan kontrol pemilihan seperti Switch, RadioButton, atau
Checkbox, Anda biasanya menaikkan perilaku yang dapat diklik ke penampung induk dengan
menyetel callback klik pada composable menjadi null, dan menambahkan
pengubah toggleable atau selectable ke composable induk.
@Composable private fun CheckableRow() { MaterialTheme { var checked by remember { mutableStateOf(false) } Row( Modifier .toggleable( value = checked, role = Role.Checkbox, onValueChange = { checked = !checked } ) .padding(16.dp) .fillMaxWidth() ) { Text("Option", Modifier.weight(1f)) Checkbox(checked = checked, onCheckedChange = null) } } }
Jika ukuran composable yang dapat diklik lebih kecil dari ukuran target sentuh minimum, Compose masih akan meningkatkan ukuran target sentuh. Hal ini dilakukan dengan memperluas ukuran target sentuh di luar batas composable.
Contoh berikut berisi Box yang dapat diklik dengan ukuran sangat kecil. Area target sentuh
otomatis diperluas di luar batas Box, sehingga mengetuk
di samping Box tetap akan memicu peristiwa klik.
@Composable private fun SmallBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .size(1.dp) ) } }
Untuk mencegah kemungkinan tumpang-tindih di antara area sentuh composable yang berbeda, selalu
gunakan ukuran minimum yang cukup besar untuk composable. Dalam contoh, ini berarti menggunakan pengubah sizeIn untuk menyetel ukuran minimum kotak dalam:
@Composable private fun LargeBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .sizeIn(minWidth = 48.dp, minHeight = 48.dp) ) } }
Elemen grafis
Saat Anda menentukan composable Image atau Icon, tidak ada cara otomatis bagi framework Android untuk memahami apa yang sedang ditampilkan aplikasi. Anda harus meneruskan deskripsi teks dari elemen grafis.
Bayangkan layar tempat pengguna dapat berbagi halaman saat ini dengan teman. Layar ini berisi ikon berbagi yang dapat diklik:
Berdasarkan ikon tersebut saja, framework Android tidak dapat mendeskripsikannya kepada pengguna dengan gangguan penglihatan. Framework Android memerlukan deskripsi teks tambahan untuk ikonnya.
Parameter contentDescription menjelaskan elemen grafis. Gunakan string yang dilokalkan, karena string ini terlihat oleh pengguna.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Beberapa elemen grafis hanyalah sebuah hiasan dan Anda mungkin tidak ingin menyampaikannya kepada pengguna. Saat menyetel parameter contentDescription ke null, Anda menunjukkan pada framework Android bahwa elemen ini tidak memiliki tindakan atau status terkait.
@Composable private fun PostImage(post: Post, modifier: Modifier = Modifier) { val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1) Image( painter = image, // Specify that this image has no semantic meaning contentDescription = null, modifier = modifier .size(40.dp, 40.dp) .clip(MaterialTheme.shapes.small) ) }
contentDescription terutama dimaksudkan untuk digunakan pada elemen grafis, seperti gambar. Komponen Material, seperti Button atau Text, dan perilaku
yang dapat ditindaklanjuti, seperti clickable atau toggleable, dilengkapi dengan semantik
yang telah ditentukan sebelumnya yang menjelaskan perilaku intrinsiknya, dan dapat diubah melalui
Compose API lainnya.
Elemen interaktif
Material dan Foundation Compose API membuat elemen UI yang dapat berinteraksi dengan pengguna melalui clickable dan toggleable API pengubah. Karena
komponen yang dapat berinteraksi dapat terdiri dari beberapa elemen, clickable dan
toggleable menggabungkan semantik turunan secara default, sehingga komponen
diperlakukan sebagai satu entity logis.
Misalnya, Button Material dapat terdiri dari ikon turunan dan beberapa
teks. Daripada memperlakukan anak-anak sebagai individu, Material
Button menggabungkan semantik turunannya secara default, sehingga layanan
aksesibilitas dapat mengelompokkannya dengan tepat:
Demikian pula, penggunaan pengubah clickable juga menyebabkan composable
menggabungkan semantik turunannya menjadi satu entity, yang dikirim ke
layanan aksesibilitas dengan representasi tindakan yang sesuai:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
Anda juga dapat menetapkan onClickLabel tertentu pada elemen yang dapat diklik induk untuk memberikan
informasi tambahan ke layanan aksesibilitas dan menawarkan representasi
tindakan yang lebih sempurna:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
Dengan menggunakan TalkBack sebagai contoh, pengubah clickable ini dan label kliknya
akan memungkinkan TalkBack memberikan petunjuk tindakan "Ketuk dua kali untuk membuka
artikel ini", bukan masukan default yang lebih umum "Ketuk dua kali untuk
mengaktifkan".
Masukan ini berubah bergantung pada jenis tindakan. Klik lama akan memberikan petunjuk TalkBack "Ketuk dua kali dan tahan untuk", diikuti dengan label:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
Dalam beberapa kasus, Anda mungkin tidak memiliki akses langsung ke pengubah clickable (misalnya, saat ditetapkan di suatu tempat di lapisan bertingkat yang lebih rendah),tetapi tetap ingin mengubah label pengumuman dari default. Untuk melakukannya, pisahkan setelan
clickable dari pengubahan pengumuman dengan menggunakan pengubah semantics
dan menetapkan label klik di sana, untuk mengubah representasi tindakan:
@Composable private fun ArticleList(openArticle: () -> Unit) { NestedArticleListItem( // Clickable is set separately, in a nested layer: onClickAction = openArticle, // Semantics are set here: modifier = Modifier.semantics { onClick( label = "Open this article", action = { // Not needed here: openArticle() true } ) } ) }
Anda tidak perlu meneruskan tindakan klik dua kali. API Compose yang ada, seperti
clickable atau Button, menanganinya untuk Anda. Logika penggabungan memverifikasi
bahwa label dan tindakan pengubah terluar dilakukan untuk informasi yang
ada. Pada contoh sebelumnya, NestedArticleListItem otomatis
meneruskan tindakan klik openArticle() ke semantik clickable-nya. Anda dapat
membiarkan tindakan klik null di tindakan pengubah semantik kedua. Namun,
label klik diambil dari pengubah semantik kedua
onClick(label = "Open this document") karena tidak ada di yang pertama.
Anda mungkin mengalami skenario saat Anda mengharapkan semantik turunan digabungkan ke dalam semantik induk, tetapi hal itu tidak terjadi. Lihat Menggabungkan dan menghapus untuk mengetahui informasi yang lebih mendalam.
Komponen kustom
Saat membuat komponen kustom, tinjau penerapan komponen serupa di library Material atau library Compose lainnya. Kemudian,
tiru atau ubah perilaku aksesibilitasnya sesuai kebutuhan. Misalnya, jika Anda mengganti Checkbox Material dengan penerapan Anda sendiri, melihat penerapan Checkbox yang ada akan mengingatkan Anda untuk menambahkan pengubah triStateToggleable, yang menangani properti aksesibilitas untuk komponen. Selain itu, gunakan banyak pengubah Foundation, karena hal ini mencakup pertimbangan aksesibilitas bawaan dan praktik Compose yang ada yang dibahas di bagian ini.
Anda juga dapat menemukan contoh komponen tombol kustom di bagian Semantik yang jelas dan ditetapkan, serta informasi yang lebih mendetail tentang cara mendukung aksesibilitas di komponen kustom dalam pedoman API.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Aksesibilitas di Compose
- Menguji tata letak Compose Anda