Aby ułatwić osobom z niepełnosprawnościami korzystanie z Twojej aplikacji, zaprojektuj do obsługi najważniejszych ułatwień dostępu.
Weź pod uwagę minimalne rozmiary docelowych elementów dotykowych
Każdy element na ekranie, który można kliknąć, dotknąć lub w inny sposób aktywować, wystarczająco dużych, by zapewnić niezawodną interakcję. Podczas dobierania rozmiaru tych elementów pamiętaj, Ustaw minimalny rozmiar na 48 dp, by zachować zgodność z Material Design ze wskazówkami dotyczącymi ułatwień dostępu.
Komponenty materiałowe – takie jak Checkbox
, RadioButton
, Switch
,
Slider
i Surface
– ustaw ten minimalny rozmiar wewnętrznie, ale tylko
gdy komponent może odbierać działania użytkownika. Jeśli na przykład Checkbox
ma
jego parametr onCheckedChange
ma wartość inną niż null, pole wyboru zawiera
dopełnienie musi mieć szerokość i wysokość co najmniej 48 dp.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }
Jeśli parametr onCheckedChange
ma wartość null, dopełnienie nie jest stosowane.
uwzględnionych, ponieważ z komponentem nie można korzystać bezpośrednio.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }
Implementując ustawienia wyboru, takie jak Switch
, RadioButton
lub
Checkbox
, zazwyczaj zwiększa się ruch klikalny na kontener nadrzędny
wywołanie zwrotne kliknięcia dla funkcji null
i dodaj do funkcji toggleable
lub
Modyfikator selectable
do nadrzędnej funkcji kompozycyjnej.
@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) } } }
Gdy rozmiar klikalnego elementu kompozycyjnego jest mniejszy niż minimalny docelowy element dotykowy nadal zwiększa rozmiar docelowego elementu dotykowego. Robi to, rozwijając rozmiar docelowego elementu dotykowego wykracza poza granice funkcji kompozycyjnej.
Poniższy przykład zawiera bardzo mały klikalny Box
. Docelowy element dotykowy
obszar jest automatycznie rozszerzany poza granice obszaru Box
, więc
obok Box
nadal wywołuje zdarzenie kliknięcia.
@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) ) } }
Aby uniknąć nakładania się obszarów dotykowych różnych elementów kompozycyjnych, zawsze
używaj wystarczająco dużego minimalnego rozmiaru elementu kompozycyjnego. W tym przykładzie
średnia z modyfikatorem sizeIn
do ustawienia minimalnego rozmiaru wewnętrznego pola:
@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) ) } }
Dodaj etykiety kliknięć
Etykieta kliknięcia pozwala nadać znaczenie semantycznemu działaniu polegającemu na kliknięciu kompozycyjne. Etykiety kliknięć informują, co się dzieje, gdy użytkownik wchodzi w interakcję z tagiem kompozycyjne. Usługi ułatwień dostępu korzystają z etykiet kliknięć, aby opisać aplikację użytkowników o określonych potrzebach.
Aby ustawić etykietę kliknięcia, przekaż parametr w modyfikatorze 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 ) ) { // .. } }
Jeśli nie masz dostępu do klikalnego modyfikatora, etykietę kliknięcia w modyfikatorze semantyki:
@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) } ) { // .. } }
Opisz elementy wizualne
Gdy zdefiniujesz kompozycję Image
lub Icon
, nie będzie
automatyczny sposób określania przez platformę Androida, czym jest aplikacja
które są wyświetlane. Musisz przekazać opis tekstowy elementu wizualnego.
Wyobraź sobie ekran, na którym użytkownik może udostępnić bieżącą stronę znajomym. Ten Na ekranie znajduje się ikona udostępniania, którą można kliknąć:
Sama ikona nie jest w stanie opisać tego działania za pomocą platformy Androida. niepełnosprawnego użytkownika. Platforma Androida wymaga dodatkowego opisu ikonę.
Parametr contentDescription
opisuje element wizualny. Użyj
ciągu znaków, ponieważ są one widoczne dla użytkownika.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Niektóre elementy wizualne mają charakter czysto dekoracyjny i nie chcesz się z nimi komunikować
i jak ich używać. Ustawienie parametru contentDescription
na null
wskazać platformie Androida, że ten element nie ma powiązanego
działania lub stanu.
@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) ) }
To Ty decydujesz, czy dany element wizualny wymaga
contentDescription
Zastanów się, czy element przekazuje informacje,
do wykonania zadania. Jeśli nie, lepiej zostawić
opis.
Scalanie elementów
Usługi ułatwień dostępu takie jak Talkback i Switch Access umożliwiają użytkownikom skupienie się między elementami na ekranie. Ważne jest, aby elementy skupiały się na z odpowiedniej szczegółowości. Gdy każda funkcja kompozycyjna niskiego poziomu na ekranie jest niezależnie od siebie, użytkownicy muszą wykonywać wiele działań, aby poruszać się po ekranie. Jeśli elementy połączą się zbyt intensywnie, użytkownicy mogą nie zrozumieć, elementy należą do siebie
Gdy zastosujesz modyfikator clickable
do funkcji kompozycyjnej, funkcja Utwórz
automatycznie łączy wszystkie elementy funkcji kompozycyjnej. Dotyczy to również
ListItem
; scalane elementy listy, ułatwienia dostępu
usługi postrzegają je jako jeden element.
Można mieć zestaw elementów kompozycyjnych, które tworzą grupę logiczną, ale grupy nie można kliknąć ani być częścią elementu listy. Nadal przyda Ci się ułatwienia dostępu i traktować je jako jeden element. Wyobraź sobie na przykład utwór kompozycyjny, wyświetla awatar użytkownika, jego nazwę oraz dodatkowe informacje:
Możesz włączyć opcję Utwórz, aby scalić te elementy, za pomocą przycisku mergeDescendants
w modyfikatorze semantics
. W ten sposób usługi ułatwień dostępu
zaznacz tylko scalony element i wszystkie właściwości semantyczne elementów podrzędnych
zostaną scalone.
@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") } } }
Usługi ułatwień dostępu skupiają się teraz na całym kontenerze naraz, scalając ich treści:
Dodaj działania niestandardowe
Przyjrzyj się temu elementowi listy:
Gdy używasz czytnika ekranu, takiego jak TalkBack, aby usłyszeć, co jest wyświetlane na najpierw cały element, a potem ikonę zakładki.
W przypadku długiej listy może się to bardzo powtarzać. Lepszym sposobem jest
zdefiniować działanie niestandardowe, które pozwala użytkownikowi dodać element do zakładek. Pamiętaj
musisz też wyraźnie usunąć działanie ikony zakładki
aby mieć pewność, że nie zostanie wybrana przez usługę ułatwień dostępu. Ten
można użyć modyfikatora 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 { } ) } }
Opisz stan elementu
Funkcja kompozycyjna może zdefiniować element stateDescription
semantyczny, którego
Platforma Androida używa do odczytywania stanu, w jakim znajduje się funkcja kompozycyjna. Dla:
na przykład włączana funkcja kompozycyjna może znajdować się lub „niezaznaczone”
stanu. W niektórych przypadkach możesz chcieć zastąpić domyślny opis stanu
używanych przez funkcję tworzenia wiadomości. Aby to zrobić, jawnie określ stan
etykiet opisu przed zdefiniowaniem funkcji kompozycyjnej jako przełączania:
@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() } ) ) { /* ... */ } }
Zdefiniuj nagłówki
Aplikacje czasami wyświetlają wiele treści na jednym ekranie w kontenerze z możliwością przewijania. Ekran może np. zawierać pełną treść artykułu, który użytkownik czyta:
Użytkownicy z niepełnosprawnościami mają problemy z poruszaniem się po takim ekranie. Do pomocy nawigacji, wskaż, które elementy są nagłówkami. W poprzednim przykładzie każda z tych wartości tytuł podsekcji można zdefiniować jako nagłówek dotyczący ułatwień dostępu. Niektóre usługi ułatwień dostępu, takie jak Talkback, pozwalają użytkownikom do nagłówka.
W narzędziu Compose wskazujesz, że funkcja kompozycyjna jest nagłówkiem, definiując
Usługa semantics
:
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
Obsługa niestandardowych elementów kompozycyjnych
Za każdym razem, gdy zmienisz w aplikacji określone komponenty Material Design na niestandardowe należy pamiętać o ułatwieniach dostępu.
Załóżmy, że zastępujesz Material Checkbox
własną implementacją.
Możesz zapomnieć o dodaniu modyfikatora triStateToggleable
, który blokuje
właściwości ułatwień dostępu tego komponentu.
Jako zasadę należy wziąć pod uwagę implementację komponentu w w bibliotece Material Design, i naśladują wszelkie dostępne funkcje. Dodatkowo, zamiast na poziomie interfejsu, używaj modyfikatorów fundamentów. modyfikatory, które domyślnie uwzględniają kwestie ułatwień dostępu.
Testowanie implementacji komponentu niestandardowego za pomocą wielu usług ułatwień dostępu, aby sprawdzić ich działanie.
Dodatkowe materiały
- Ułatwienia dostępu: podstawowe pojęcia i techniki wspólne dla wszystkich programistów aplikacji na Androida.
- Tworzenie aplikacji z ułatwieniami dostępu: kluczowe czynności które można usprawnić,
- Zasady ulepszania aplikacji Ułatwienia dostępu: podstawowe zasady pamiętaj o nich podczas pracy nad ułatwianiem dostępu do aplikacji
- Testowanie ułatwień dostępu: Testowanie zasad i narzędzi ułatwień dostępu na Androidzie