API Material, Compose UI, dan Foundation menerapkan dan menawarkan banyak praktik yang mudah diakses 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 standar yang mencakup kasus penggunaan standar. Namun, selalu periksa kembali apakah setelan default ini sesuai dengan kebutuhan aksesibilitas Anda. Jika tidak, Compose menyediakan cara untuk memenuhi persyaratan yang lebih spesifik.
Memahami semantik dan pola aksesibilitas default di Compose API akan 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—menyetel 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 container 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. 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 bagian 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) ) } }
Jika elemen harus mempertahankan ukuran terlihat yang lebih kecil, gunakan
pengubah minimumInteractiveComponentSize dari Material 3. Komponen ini
menyediakan setidaknya 48 dp ruang tata letak di setiap dimensi dan memusatkan
elemen di ruang tersebut, sehingga elemen mempertahankan ukuran yang digambar dan elemen
di sekitarnya berpindah untuk memberi ruang. Pengubah tidak memperluas target sentuh
itu sendiri: pengubah menyisakan ruang dalam tata letak untuk perluasan yang dijelaskan sebelumnya.
Komponen Material seperti Checkbox menggunakan pengubah ini secara internal. Tempatkan
sebelum pengubah ukuran, karena pengubah ukuran sebelum pengubah ini membatasi ruang
yang dapat dicadangkan.
@Composable private fun MinimumInteractiveBox() { var clicked by remember { mutableStateOf(false) } Row(verticalAlignment = Alignment.CenterVertically) { Box( Modifier .clickable { clicked = !clicked } .minimumInteractiveComponentSize() .size(24.dp) .background(if (clicked) Color.DarkGray else Color.Black) ) Text("Option") } }
Elemen grafis
Saat Anda menentukan composable Image atau Icon, tidak ada cara otomatis bagi framework Android untuk memahami apa yang 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 mendeskripsikan elemen grafis. Gunakan string yang dilokalkan, karena string ini dapat dilihat 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 ditetapkan sebelumnya yang menjelaskan perilaku intrinsiknya, dan dapat diubah melalui
Compose API lainnya.
Elemen interaktif
API Compose Material dan Foundation membuat elemen UI yang dapat digunakan pengguna untuk berinteraksi
melalui API pengubah clickable dan toggleable. Karena
komponen yang dapat berinteraksi mungkin terdiri dari beberapa elemen, clickable dan
toggleable menggabungkan semantik turunannya secara default, sehingga komponen
diperlakukan sebagai satu entity logis.
Misalnya, Button Material mungkin terdiri dari ikon turunan dan beberapa
teks. Alih-alih memperlakukan turunan sebagai individu, Button
Material menggabungkan semantik turunannya secara default, sehingga layanan
aksesibilitas dapat mengelompokkannya sebagaimana mestinya:
Demikian pula, menggunakan 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 induk yang dapat diklik untuk memberikan
informasi tambahan ke layanan aksesibilitas dan menawarkan representasi
tindakan yang lebih baik:
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, yaitu "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 masih ingin
mengubah label pengumuman dari default. Untuk melakukannya, pisahkan setelan
clickable dari mengubah pengumuman 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. Compose API yang ada, seperti
clickable atau Button, akan menangani hal ini untuk Anda. Logika penggabungan memverifikasi
bahwa label dan tindakan pengubah terluar diambil untuk informasi yang
ada. Pada contoh sebelumnya, NestedArticleListItem otomatis
meneruskan tindakan klik openArticle() ke semantik clickable-nya. Anda dapat
membiarkan tindakan klik null dalam tindakan pengubah semantik kedua. Namun,
label klik diambil dari pengubah semantik kedua
onClick(label = "Open this document") karena tidak ada di pengubah 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 implementasi
komponen serupa di library Material atau library Compose lainnya. Kemudian,
tiru atau ubah perilaku aksesibilitasnya sebagaimana mestinya. 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 Menghapus dan menetapkan semantik, serta informasi yang lebih mendetail tentang cara mendukung aksesibilitas di komponen kustom dalam panduan API.
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Aksesibilitas di Compose
- Menguji tata letak Compose Anda