Prinsip-prinsip untuk meningkatkan aksesibilitas aplikasi

Untuk membantu pengguna yang memiliki kebutuhan aksesibilitas, framework Android memungkinkan Anda membuat layanan aksesibilitas yang dapat menampilkan konten dari aplikasi kepada pengguna dan juga mengoperasikan aplikasi atas nama mereka.

Android menyediakan beberapa layanan aksesibilitas sistem, termasuk:

  • TalkBack: membantu pengguna yang memiliki gangguan penglihatan atau tunanetra. TalkBack mengumumkan konten melalui suara yang disintesis dan melakukan tindakan pada aplikasi sebagai respons terhadap gestur pengguna.
  • Tombol Akses: membantu penyandang gangguan motorik. Fitur ini menandai elemen interaktif dan melakukan tindakan sebagai respons terhadap penekanan tombol oleh pengguna. Fitur ini memungkinkan kontrol perangkat hanya menggunakan satu atau dua tombol.

Untuk membantu orang yang memerlukan aksesibilitas agar berhasil menggunakan aplikasi Anda, aplikasi Anda harus mengikuti praktik terbaik yang dijelaskan di halaman ini, yang dibuat berdasarkan pedoman yang dijelaskan dalam Membuat aplikasi lebih mudah diakses.

Setiap praktik terbaik ini, yang dijelaskan di bagian berikut, dapat lebih meningkatkan aksesibilitas aplikasi Anda:

Elemen label
Pengguna harus dapat memahami konten dan tujuan setiap elemen UI yang interaktif dan bermakna dalam aplikasi Anda.
Menambahkan tindakan aksesibilitas
Dengan menambahkan tindakan aksesibilitas, Anda dapat memungkinkan pengguna layanan aksesibilitas menyelesaikan alur penggunaan penting dalam aplikasi Anda.
Menggunakan fitur aksesibilitas bawaan
Compose menawarkan banyak perilaku aksesibilitas secara default. Manfaatkan perilaku aksesibilitas yang telah ditentukan untuk membuat komponen Anda dapat diakses dengan sedikit atau tanpa pekerjaan tambahan. Compose juga menyediakan cara untuk mendukung persyaratan aksesibilitas yang lebih spesifik yang tidak tercakup dalam fitur default.
Menggunakan isyarat selain warna
Pengguna harus dapat membedakan dengan jelas antara kategori elemen dalam UI. Untuk melakukannya, gunakan pola dan posisi serta warna untuk menunjukkan perbedaannya.
Menjadikan konten media lebih mudah diakses
Tambahkan deskripsi ke konten video atau audio aplikasi Anda agar pengguna yang mengonsumsi konten ini tidak perlu sepenuhnya mengandalkan isyarat visual atau audio.

Elemen label

Penting untuk memberikan label yang berguna dan deskriptif kepada pengguna untuk setiap elemen UI interaktif di aplikasi Anda. Setiap label harus menjelaskan semantik elemen tertentu—yaitu, arti dan tujuan elemen. Pembaca layar seperti TalkBack dapat memberitahukan label ini kepada pengguna.

Dalam sebagian besar kasus, Compose API dan Material memiliki dukungan aksesibilitas default. Namun, jika Anda perlu menentukan properti semantik elemen UI secara manual, gunakan pengubah semantics dan properti contentDescription. Untuk mengetahui informasi selengkapnya tentang semantik, lihat Semantik.

Bagian berikut menjelaskan beberapa teknik pelabelan lainnya.

Elemen yang dapat diedit

Saat memberi label pada elemen yang dapat diedit, seperti kolom teks, sebaiknya tampilkan teks yang memberikan contoh input yang valid dalam elemen itu sendiri, selain menyediakan teks contoh ini untuk pembaca layar. Dalam situasi ini, Anda dapat menggunakan teks placeholder, yang juga disebut teks petunjuk.

Dalam contoh berikut, TextField memiliki parameter placeholder yang memberikan teks petunjuk.

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

Kolom teks juga biasanya memiliki label deskriptif yang sesuai, yang menjelaskan karakter yang harus dimasukkan pengguna sebagai input.

Dalam contoh berikut, TextField memiliki parameter label yang memberikan deskripsi aksesibilitas.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

Untuk mengetahui informasi selengkapnya tentang teks dan input pengguna, lihat Mengonfigurasi kolom teks.

Elemen dalam koleksi

Saat menambahkan label ke elemen koleksi, setiap label harus unik. Dengan cara ini, layanan aksesibilitas sistem dapat merujuk ke tepat satu elemen di layar saat mengumumkan label. Korespondensi ini memungkinkan pengguna mengetahui kapan mereka beralih di UI atau saat mereka memindahkan fokus ke elemen yang sudah mereka temukan.

Misalnya, saat Anda memiliki LazyColumn atau LazyRow, gunakan pengubah semantics untuk menetapkan collectionItemInfo unik ke setiap item, seperti yang ditunjukkan dalam cuplikan berikut:

MilkyWayList(
    modifier = Modifier
        .semantics {
            collectionInfo = CollectionInfo(
                rowCount = milkyWay.count(),
                columnCount = 1
            )
        }
) {
    milkyWay.forEachIndexed { index, text ->
        Text(
            text = text,
            modifier = Modifier.semantics {
                collectionItemInfo =
                    CollectionItemInfo(index, 0, 0, 0)
            }
        )
    }
}

Untuk mengetahui informasi selengkapnya tentang properti semantik untuk daftar dan petak, lihat Informasi daftar dan item.

Grup konten terkait

Jika aplikasi Anda menampilkan beberapa elemen UI yang membentuk grup alami, seperti detail lagu atau atribut pesan, susun elemen ini dalam penampung induk (seperti Column, Row, atau Box). Gunakan pengubah semantics penampung induk untuk menyetel mergeDescendants ke true.

Dengan cara ini, layanan aksesibilitas dapat menampilkan deskripsi konten elemen dalam satu per satu, dalam satu pengumuman. Menggabungkan elemen terkait membantu pengguna teknologi pendukung menemukan informasi di layar secara lebih efisien.

Dalam cuplikan berikut, composable Row bertindak sebagai penampung induk. Dalam Row, terdapat elemen terkait yang menampilkan metadata untuk postingan blog—avatar penulis, nama penulis, dan perkiraan waktu membaca. Menyetel mergeDescendants ke true akan mengelompokkan elemen dalam ini, sehingga layanan aksesibilitas dapat memperlakukannya sebagai satu unit.

@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")
        }
    }
}

Saat mengelompokkan elemen terkait seperti pada contoh sebelumnya, buat hanya penampung induk yang interaktif. Hindari menambahkan pengubah clickable atau focusable ke elemen turunan dalam. Sebagai gantinya, terapkan pengubah ke Row atau Column induk.

Karena layanan aksesibilitas membacakan deskripsi elemen inti dalam satu kalimat, penting untuk membuat setiap deskripsi sesingkat mungkin tetapi tetap menyampaikan maksud elemen tersebut.

Catatan: Secara umum, saat membuat deskripsi konten untuk grup, hindari menggabungkan teks turunannya. Tindakan ini membuat deskripsi grup menjadi rentan, dan saat teks turunan berubah, deskripsi grup mungkin tidak lagi cocok dengan teks yang terlihat.

Dalam konteks daftar atau petak, pembaca layar mungkin menggabungkan teks dari node teks turunan elemen daftar atau petak. Sebaiknya hindari mengubah pengumuman ini.

Untuk mengetahui informasi selengkapnya tentang semantik penggabungan, lihat Menggabungkan dan menghapus.

Judul dalam teks

Beberapa aplikasi menggunakan judul untuk meringkas grup teks yang muncul di layar. Jika elemen tertentu mewakili judul, Anda dapat menunjukkan tujuannya untuk layanan aksesibilitas dengan menetapkan properti heading di pengubah semantics.

@Composable
private fun Subsection(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.headlineSmall,
        modifier = Modifier.semantics { heading() }
    )
}

Pengguna layanan aksesibilitas dapat memilih untuk memilih opsi navigasi antar-judul, bukan antar-paragraf atau antar-kata. Fleksibilitas ini akan meningkatkan pengalaman navigasi teks.

Untuk mengetahui informasi selengkapnya tentang properti semantik heading, lihat Judul.

Judul panel aksesibilitas

Di Android 9 (API level 28) dan yang lebih tinggi, Anda dapat memberikan judul yang mudah diakses untuk panel layar. Untuk tujuan aksesibilitas, panel adalah bagian jendela yang terlihat berbeda.

Agar layanan aksesibilitas memahami perilaku panel yang mirip jendela, berikan judul deskriptif ke panel aplikasi Anda. Selanjutnya, layanan aksesibilitas dapat memberikan informasi yang lebih terperinci kepada pengguna saat tampilan atau konten panel berubah.

ShareSheet(
    message = "Choose how to share this photo",
    modifier = Modifier
        .fillMaxWidth()
        .align(Alignment.TopCenter)
        .semantics { paneTitle = "New bottom sheet" }
)

Untuk mengetahui informasi selengkapnya tentang properti semantik paneTitle, lihat Komponen seperti jendela.

Elemen dekoratif

Jika elemen di UI Anda hanya ada untuk tujuan penspasian visual atau tampilan visual, tetapkan properti yang sesuai pada elemen untuk menunjukkan bahwa layanan aksesibilitas dapat mengabaikannya.

Untuk composable Image atau Icon, tetapkan contentDescription = null. Untuk elemen dekoratif murni lainnya yang tidak memberikan konteks atau fungsi, Anda dapat menggunakan hideFromAccessibility. Properti semantik ini memberi tahu layanan aksesibilitas untuk mengabaikan item.

Jika composable interaktif berisi elemen turunan dekoratif dan non-interaktif, gunakan clearAndSetSemantics untuk memastikan bahwa layanan aksesibilitas tidak melintasinya. Perhatikan bahwa clearAndSetSemantics sepenuhnya menghapus semantik default elemen dan turunannya. Hal ini memungkinkan Anda menentukan elemen aksesibilitas baru yang terpadu. Biasanya, Anda menggunakan pendekatan ini untuk komponen kustom yang kompleks.

Dalam contoh berikut, Icon dan Text adalah elemen turunan dekoratif di dalam tombol kustom. Untuk mencegah layanan aksesibilitas melintasi turunan ini satu per satu, Anda dapat menghapus semantiknya menggunakan clearAndSetSemantics pada induk Row. Kode ini memberi tahu layanan aksesibilitas untuk memperlakukan seluruh Row sebagai tombol yang dapat dilalui:

// Developer might intend this to be a toggleable.
// Using `clearAndSetSemantics`, on the Row, a clickable modifier is applied,
// a custom description is set, and a Role is applied.

@Composable
fun FavoriteToggle() {
    val checked = remember { mutableStateOf(true) }
    Row(
        modifier = Modifier
            .toggleable(
                value = checked.value,
                onValueChange = { checked.value = it }
            )
            .clearAndSetSemantics {
                stateDescription = if (checked.value) "Favorited" else "Not favorited"
                toggleableState = ToggleableState(checked.value)
                role = Role.Switch
            },
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = null // not needed here

        )
        Text("Favorite?")
    }
}

Untuk informasi selengkapnya tentang menghapus semantik, lihat Menghapus dan menetapkan semantik.

Menambahkan tindakan aksesibilitas

Penting untuk memastikan bahwa pengguna layanan aksesibilitas memiliki cara untuk menyelesaikan semua alur pengguna di aplikasi Anda.

Jika interaksi composable kustom Anda mengubah status aplikasi dengan cara yang tidak jelas, berikan label deskriptif untuk tindakan ketuk standar menggunakan parameter seperti onClickLabel atau onLongClickLabel di Modifier.clickable atau Modifier.combinedClickable.

Untuk interaksi kompleks yang tidak dapat dipetakan ke ketukan standar, gunakan customActions.

Misalnya, jika aplikasi Anda memungkinkan pengguna menarik item ke lokasi lain atau menggeser item dalam daftar, Anda dapat memberikan cara alternatif untuk menyelesaikan alur pengguna ini dengan mengekspos tindakan ke layanan aksesibilitas. Dengan cara ini, pengguna TalkBack, Voice Access, atau Tombol Akses dapat melakukan tindakan yang mungkin hanya tersedia melalui gestur.

Di Compose, Anda dapat menentukan tindakan aksesibilitas kustom melalui properti customActions di pengubah semantics, menggunakan CustomAccessibilityAction.

Misalnya, jika aplikasi Anda memungkinkan pengguna menggeser item untuk menutupnya, Anda dapat mengekspos fungsi tersebut melalui tindakan aksesibilitas kustom:

SwipeToDismissBox(
    modifier = Modifier.semantics {
        // Represents the swipe to dismiss for accessibility
        customActions = listOf(
            CustomAccessibilityAction(
                label = "Remove article from list",
                action = {
                    removeArticle()
                    true
                }
            )
        )
    },
    state = rememberSwipeToDismissBoxState(),
    backgroundContent = {}
) {
    ArticleListItem()
}

Dengan tindakan aksesibilitas kustom yang diterapkan, pengguna dapat mengakses tindakan melalui menu tindakan.

Untuk informasi selengkapnya tentang tindakan kustom, lihat Tindakan kustom.

Membuat tindakan yang tersedia dapat dipahami

Saat elemen UI mendukung tindakan seperti sentuh lama, layanan aksesibilitas seperti TalkBack akan mengumumkannya sebagai "Ketuk dua kali dan tahan untuk menekan lama".

Pengumuman umum ini tidak memberi pengguna konteks apa pun tentang fungsi tindakan sentuh & tahan.

Agar pengumuman ini lebih berguna, tentukan deskripsi yang bermakna untuk tindakan tersebut.

Di Compose, pengubah interaksi standar seperti clickable dan combinedClickable memiliki parameter bawaan (yaitu onClickLabel dan onLongClickLabel) yang dapat Anda gunakan untuk memberikan deskripsi tindakan, seperti dalam contoh berikut:

var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) }
val haptics = LocalHapticFeedback.current
LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) {
    items(photos, { it.id }) { photo ->
        ImageItem(
            photo,
            Modifier
                .combinedClickable(
                    onClick = { activePhotoId = photo.id },
                    onLongClick = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        contextMenuPhotoId = photo.id
                    },
                    onLongClickLabel = stringResource(R.string.open_context_menu)
                )
        )
    }
}
if (contextMenuPhotoId != null) {
    PhotoActionsSheet(
        photo = photos.first { it.id == contextMenuPhotoId },
        onDismissSheet = { contextMenuPhotoId = null }
    )
}

Tindakan ini akan membuat TalkBack mengucapkan "Buka menu konteks", sehingga membantu pengguna memahami tujuan tindakan tersebut.

Anda juga dapat menentukan label secara langsung di pengubah semantics.

Untuk mengetahui informasi selengkapnya tentang cara merespons ketukan dan klik, lihat Ketuk dan tekan serta Elemen interaktif.

Menggunakan fitur aksesibilitas bawaan

Saat mendesain UI aplikasi, manfaatkan fitur aksesibilitas bawaan untuk menghindari penerapan ulang fungsi yang sudah ada. API Material, Compose UI, dan Foundation menerapkan dan menawarkan banyak praktik yang mudah diakses secara default.

Di Jetpack Compose, gunakan composable bawaan seperti Button, Switch, dan Checkbox untuk membuat UI yang mudah diakses. Komponen ini dilengkapi dengan pengubah semantics, seperti role dan stateDescription, yang dapat Anda gunakan untuk membuat aplikasi lebih mudah diakses.

Menerapkan semantik ke komponen kustom

Saat membuat komponen kustom, perhatikan jenis dukungan aksesibilitas yang diperlukan komponen ini untuk memenuhi perannya. Sering kali, Compose API standar yang sudah Anda gunakan—seperti clickable, toggleable, atau selectable—sudah cukup karena API tersebut otomatis mengisi hierarki semantik untuk Anda.

Namun, beberapa komponen memerlukan informasi yang lebih spesifik daripada yang disediakan pengubah standar. Dalam kasus ini, cari pengubah khusus (seperti triStateToggleable) atau, jika tidak ada, berikan semantik secara eksplisit menggunakan Modifier.semantics tingkat rendah.

Misalnya, pertimbangkan TriStateSwitch, tombol dengan tiga status (Aktif, Nonaktif, dan Tidak Pasti).

Meskipun pengubah toggleable standar mengasumsikan dua status, pengubah triStateToggleable menangani kompleksitas status ketiga. Fungsi ini otomatis menetapkan aksesibilitas Role (Switch) dan State. Dengan cara ini, layanan aksesibilitas menerima informasi yang akurat, dan Anda tidak perlu menentukan semantik secara manual.

Cuplikan kode berikut menunjukkan TriStateSwitch yang menggunakan pendekatan ini:

@Composable
fun TriStateSwitch(
    state: ToggleableState,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    // A real implementation would include custom drawing for the switch.
    // This example uses a Box to demonstrate the semantics.
    Box(
        modifier = modifier
            .size(width = 64.dp, height = 40.dp)
            // triStateToggleable handles the semantics (Role and State)
            // automatically, so explicit Modifier.semantics is not needed here.
            .triStateToggleable(
                state = state,
                onClick = onClick,
                role = Role.Switch
            )
            // Add visual feedback based on the state
            .background(
                when (state) {
                    ToggleableState.On -> Color.Green
                    ToggleableState.Off -> Color.Gray
                    ToggleableState.Indeterminate -> Color.Yellow
                }
            )
    )
}

// Usage within another composable:
var state by remember { mutableStateOf(ToggleableState.Off) }
TriStateSwitch(
    state = state,
    onClick = {
        state = when (state) {
            ToggleableState.Off -> ToggleableState.Indeterminate
            ToggleableState.Indeterminate -> ToggleableState.On
            ToggleableState.On -> ToggleableState.Off
        }
    }
)

Saat membuat komponen kustom, pastikan Anda menyediakan semua properti semantik yang relevan untuk tujuan aksesibilitas. Misalnya, jika komponen Anda meniru kontrol standar seperti tombol atau tombol beralih, properti ini mencakup peran komponen (seperti Role.Switch atau Role.Button), stateDescription (seperti "Aktif", "Nonaktif", "Dicentang", atau "Tidak dicentang"), dan label tindakan yang relevan. Untuk mengetahui informasi selengkapnya, lihat Komponen kustom.

Menggunakan petunjuk selain warna

Untuk membantu pengguna yang mengalami kekurangan daya penglihatan terhadap warna, gunakan petunjuk selain warna untuk membedakan elemen UI dalam layar aplikasi Anda. Teknik ini dapat mencakup penggunaan bentuk atau ukuran yang berbeda, memberikan pola teks atau visual, atau menambahkan masukan berbasis audio atau sentuhan (haptik) untuk menandai perbedaan elemen.

Gambar 1 menunjukkan dua versi aktivitas. Versi pertama hanya menggunakan warna untuk membedakan antara dua kemungkinan tindakan dalam alur kerja. Versi kedua menggunakan praktik terbaik yang menyertakan bentuk dan teks selain warna untuk menandai perbedaan antara kedua opsi tersebut:

Di sebelah kiri adalah layar dengan dua tombol lingkaran, satu berwarna hijau dan satu berwarna merah. Di sebelah kanan adalah layar yang sama, tetapi dua tombol lingkaran diberi label dengan teks dan ikon yang bermakna.
Gambar 1. Contoh pembuatan elemen UI hanya menggunakan warna (kiri) dan menggunakan warna, bentuk, dan teks (kanan).

Menjadikan konten media lebih mudah diakses

Jika Anda mengembangkan aplikasi yang menyertakan konten media, seperti klip video atau rekaman audio, cobalah untuk mendukung pengguna dengan berbagai jenis kebutuhan aksesibilitas dalam memahami materi. Khususnya, coba lakukan hal berikut:

  • Sertakan kontrol yang memungkinkan pengguna menjeda atau menghentikan media, mengubah volume, dan mengaktifkan atau menonaktifkan subtitel (teks).
  • Jika video menyajikan informasi yang penting untuk menyelesaikan alur kerja, berikan konten yang sama dalam format alternatif, seperti transkrip.

Referensi lainnya

Untuk informasi selengkapnya tentang cara membuat aplikasi lebih mudah diakses, lihat referensi tambahan berikut:

Codelab

Konten penayangan