Untuk membantu pengguna yang memiliki kebutuhan aksesibilitas agar berhasil menggunakan aplikasi Anda, desain aplikasi aplikasi Anda untuk mendukung persyaratan aksesibilitas utama.
Mempertimbangkan 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 mengukur elemen-elemen ini, pastikan untuk setel ukuran minimum ke 48 dp untuk mengikuti Desain Material dengan benar panduan aksesibilitas.
Komponen material—seperti Checkbox
, RadioButton
, Switch
,
Slider
, dan Surface
—tetapkan ukuran minimum ini secara internal, tetapi hanya
kapan komponen dapat menerima tindakan pengguna. Misalnya, saat Checkbox
memiliki
parameter onCheckedChange
disetel ke nilai {i>non-null<i}, kotak centang itu 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 akan
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 menghilangkan perilaku yang dapat diklik ke penampung induk, menetapkan
callback klik pada composable ke null
, dan tambahkan toggleable
atau
Pengubah 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 dan berukuran sangat kecil. Target sentuh
area secara otomatis diperluas di luar batas Box
, sehingga mengetuk
di samping Box
masih 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. Pada contoh, proses itu akan
berarti menggunakan pengubah sizeIn
untuk menetapkan 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) ) } }
Menambahkan label klik
Anda dapat menggunakan label klik untuk menambahkan makna semantik ke perilaku klik composable. Label klik menjelaskan apa yang terjadi bila pengguna berinteraksi dengan composable. Layanan aksesibilitas menggunakan label klik untuk membantu mendeskripsikan aplikasi pengguna dengan kebutuhan tertentu.
Tetapkan label klik dengan meneruskan parameter di pengubah clickable
:
@Composable private fun ArticleListItem(openArticle: () -> Unit) { Row( Modifier.clickable( // R.string.action_read_article = "read article" onClickLabel = stringResource(R.string.action_read_article), onClick = openArticle ) ) { // .. } }
Atau, jika Anda tidak memiliki akses ke pengubah yang dapat diklik, setel label klik di pengubah semantik:
@Composable private fun LowLevelClickLabel(openArticle: () -> Boolean) { // R.string.action_read_article = "read article" val readArticleLabel = stringResource(R.string.action_read_article) Canvas( Modifier.semantics { onClick(label = readArticleLabel, action = openArticle) } ) { // .. } }
Menjelaskan elemen visual
Saat menentukan composable Image
atau Icon
, tidak ada
cara otomatis agar framework Android memahami aplikasi tersebut
ditampilkan. Anda harus meneruskan deskripsi tekstual dari elemen visual.
Bayangkan layar tempat pengguna dapat berbagi halaman saat ini dengan teman. Layar ini berisi ikon berbagi yang dapat diklik:
Berdasarkan ikon saja, framework Android tidak dapat mendeskripsikannya dengan pengguna yang memiliki gangguan. Framework Android membutuhkan deskripsi tekstual tambahan tentang ikon.
Parameter contentDescription
mendeskripsikan elemen visual. Gunakan terjemahan
{i>string<i}, seperti yang 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 visual hanya bersifat dekoratif dan Anda mungkin tidak ingin berkomunikasi
mereka kepada pengguna. Jika menetapkan parameter contentDescription
ke null
, Anda
menunjukkan ke kerangka kerja Android bahwa elemen ini tidak terkait
tindakan atau status.
@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) ) }
Andalah yang memutuskan apakah elemen visual tertentu memerlukan contentDescription
. Tanyakan pada diri Anda sendiri apakah elemen
tersebut menyampaikan informasi yang
apa yang dibutuhkan pengguna
untuk melakukan tugas mereka. Jika tidak, sebaiknya biarkan
deskripsi.
Menggabungkan elemen
Layanan aksesibilitas seperti Talkback dan Tombol Akses memungkinkan pengguna memindahkan fokus ke seluruh elemen di layar. Elemen-elemen harus difokuskan pada tingkat perincian yang tepat. Saat setiap composable tingkat rendah di layar Anda berfokus secara mandiri, pengguna harus banyak berinteraksi untuk bergerak di seluruh layar. Jika elemen menggabungkan terlalu banyak elemen, pengguna mungkin tidak memahami elemen mana elemen saling berkaitan
Saat Anda menerapkan pengubah clickable
ke composable, Compose
secara otomatis menggabungkan semua elemen yang ada di composable. Hal ini juga berlaku untuk
ListItem
; elemen di dalam item daftar
digabungkan, dan aksesibilitas
melihatnya sebagai satu elemen.
Anda dapat memiliki sekumpulan composable yang membentuk grup logis, tetapi grup tersebut tidak dapat diklik atau merupakan bagian dari item daftar. Anda masih menginginkan aksesibilitas layanan untuk melihatnya sebagai satu elemen. Misalnya, bayangkan composable yang menampilkan avatar pengguna, nama mereka, dan beberapa informasi tambahan:
Anda dapat mengaktifkan Compose untuk menggabungkan elemen ini menggunakan mergeDescendants
dalam pengubah semantics
. Dengan cara ini, layanan aksesibilitas
memilih hanya elemen gabungan, dan semua properti semantik turunan
akan digabungkan.
@Composable private fun PostMetadata(metadata: Metadata) { // Merge elements below for accessibility purposes Row(modifier = Modifier.semantics(mergeDescendants = true) {}) { Image( imageVector = Icons.Filled.AccountCircle, contentDescription = null // decorative ) Column { Text(metadata.author.name) Text("${metadata.date} • ${metadata.readTimeMinutes} min read") } } }
Layanan aksesibilitas kini berfokus pada seluruh container sekaligus, menggabungkan isi kontennya:
Menambahkan tindakan kustom
Lihat item daftar berikut:
Saat Anda menggunakan pembaca layar seperti Talkback untuk mendengar apa yang ditampilkan di layar, pertama-tama memilih seluruh item, dan kemudian ikon bookmark.
Dalam daftar panjang, hal ini dapat menjadi sangat berulang. Pendekatan yang lebih baik adalah
menentukan tindakan kustom yang memungkinkan pengguna menandai item. Harap diingat
bahwa Anda juga harus secara eksplisit menghapus perilaku ikon bookmark
itu sendiri untuk memastikannya tidak
dipilih oleh layanan aksesibilitas. Ini
dilakukan dengan pengubah clearAndSetSemantics
:
@Composable private fun PostCardSimple( /* ... */ isFavorite: Boolean, onToggleFavorite: () -> Boolean ) { val actionLabel = stringResource( if (isFavorite) R.string.unfavorite else R.string.favorite ) Row( modifier = Modifier .clickable(onClick = { /* ... */ }) .semantics { // Set any explicit semantic properties customActions = listOf( CustomAccessibilityAction(actionLabel, onToggleFavorite) ) } ) { /* ... */ BookmarkButton( isBookmarked = isFavorite, onClick = onToggleFavorite, // Clear any semantics properties set on this node modifier = Modifier.clearAndSetSemantics { } ) } }
Menjelaskan status elemen
Composable dapat menentukan stateDescription
untuk semantik yang
Framework Android digunakan untuk membaca status tempat composable berada. Sebagai
contoh, composable yang dapat diganti statusnya bisa dalam status "dicentang" atau "tidak dicentang"
status. Dalam beberapa kasus, Anda mungkin ingin mengganti deskripsi status default
label yang digunakan Compose. Anda dapat melakukannya dengan menentukan status secara eksplisit
label deskripsi sebelum menentukan composable sebagai dapat diganti:
@Composable private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) { val stateSubscribed = stringResource(R.string.subscribed) val stateNotSubscribed = stringResource(R.string.not_subscribed) Row( modifier = Modifier .semantics { // Set any explicit semantic properties stateDescription = if (selected) stateSubscribed else stateNotSubscribed } .toggleable( value = selected, onValueChange = { onToggle() } ) ) { /* ... */ } }
Menentukan judul
Aplikasi terkadang menampilkan banyak konten di satu layar dalam container yang dapat di-scroll. Misalnya, layar dapat menampilkan konten lengkap artikel yang sedang dibaca pengguna:
Pengguna dengan kebutuhan aksesibilitas mengalami kesulitan menavigasi layar tersebut. Untuk membantu navigasi, menunjukkan elemen mana yang merupakan {i>heading<i}. Dalam contoh sebelumnya, masing-masing judul subbagian dapat didefinisikan sebagai judul untuk aksesibilitas. Agak besar layanan aksesibilitas, seperti TalkBack, memungkinkan pengguna untuk menavigasi langsung dari ke judul.
Di Compose, Anda menunjukkan bahwa composable adalah judul dengan menentukan
Properti semantics
:
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
Menangani composable kustom
Setiap kali Anda mengganti komponen Material tertentu di aplikasi dengan kustom versi, Anda harus selalu mempertimbangkan aksesibilitas.
Misalnya Anda mengganti Checkbox
Material dengan implementasi Anda sendiri.
Anda mungkin lupa untuk menambahkan pengubah triStateToggleable
, yang menangani
properti aksesibilitas
untuk komponen ini.
Prinsipnya adalah melihat implementasi komponen pada library Material dan meniru perilaku aksesibilitas apa pun yang dapat Anda temukan. Selain itu, gunakan banyak pengubah Foundation, berbeda dengan pengubah tingkat UI, karena hal ini mencakup pertimbangan aksesibilitas.
Menguji implementasi komponen kustom dengan beberapa layanan aksesibilitas untuk memverifikasi perilakunya.
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