Material-, Compose UI- und Foundation-APIs implementieren und bieten standardmäßig viele barrierefreie Praktiken. Sie enthalten integrierte Semantik, die ihrer jeweiligen Rolle und Funktion entspricht. Das bedeutet, dass die meisten Bedienungshilfen ohne oder mit nur geringem zusätzlichen Aufwand bereitgestellt werden.
Wenn Sie die richtigen APIs für den richtigen Zweck verwenden, haben Komponenten in der Regel vordefinierte Barrierefreiheitsfunktionen, die Standardanwendungsfälle abdecken. Prüfen Sie jedoch immer, ob diese Standardeinstellungen Ihren Anforderungen an die Barrierefreiheit entsprechen. Falls nicht, bietet Compose Möglichkeiten, spezifischere Anforderungen zu erfüllen.
Wenn Sie die standardmäßigen Semantiken und Muster für die Barrierefreiheit in Compose-APIs kennen, können Sie sie mit Blick auf die Barrierefreiheit verwenden. Außerdem können Sie so die Barrierefreiheit in benutzerdefinierten Komponenten besser unterstützen.
Mindestgrößen für Berührungszielbereiche
Bildschirmelemente, die angeklickt, angetippt oder auf sonstige Weise verwendet werden können, müssen groß genug sein, um eine zuverlässige Interaktion zu ermöglichen. Achten Sie beim Festlegen der Größe dieser Elemente darauf, die Mindestgröße auf 48 dp festzulegen, um die Material Design-Richtlinien für Bedienungshilfen einzuhalten.
Materialkomponenten wie Checkbox, RadioButton, Switch, Slider und Surface legen diese Mindestgröße intern fest, aber nur, wenn die Komponente Nutzeraktionen empfangen kann. Wenn beispielsweise für ein Checkbox der Parameter onCheckedChange auf einen Wert ungleich null festgelegt ist, enthält das Kästchen einen Innenabstand, sodass es eine Breite und Höhe von mindestens 48 dp hat.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }
Wenn der Parameter onCheckedChange auf „null“ gesetzt ist, wird der Innenabstand nicht berücksichtigt, da die Komponente nicht direkt verwendet werden kann.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }
Wenn Sie Auswahlsteuerelemente wie Switch, RadioButton oder Checkbox implementieren, heben Sie das anklickbare Verhalten in der Regel auf einen übergeordneten Container an, indem Sie den Klick-Callback für die zusammensetzbare Funktion auf null festlegen und der übergeordneten zusammensetzbaren Funktion einen toggleable- oder selectable-Modifier hinzufügen.
@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) } } }
Wenn die Größe einer anklickbaren zusammensetzbaren Funktion kleiner als die Mindestgröße des Berührungszielbereichs ist, wird die Größe des Berührungszielbereichs in Compose trotzdem erhöht. Dazu wird die Größe des Touch-Ziels über die Grenzen des Composables hinaus erweitert.
Das folgende Beispiel enthält ein sehr kleines klickbares Box. Der Bereich für das Touch-Ziel wird automatisch über die Grenzen von Box hinaus erweitert. Wenn Sie also neben Box tippen, wird das Klickereignis trotzdem ausgelöst.
@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) ) } }
Um eine mögliche Überschneidung zwischen den Touchbereichen verschiedener Composables zu vermeiden, sollten Sie immer eine ausreichend große Mindestgröße für das jeweilige Composable verwenden. Im Beispiel würde das bedeuten, dass Sie den Modifikator sizeIn verwenden, um die Mindestgröße für das innere Feld festzulegen:
@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) ) } }
Grafikelemente
Wenn Sie eine Image- oder Icon-Composable definieren, kann das Android-Framework nicht automatisch erkennen, was in der App angezeigt wird. Sie müssen eine Textbeschreibung des Grafikelements übergeben.
Stellen Sie sich einen Bildschirm vor, auf dem der Nutzer die aktuelle Seite mit Freunden teilen kann. Dieser Bildschirm enthält ein anklickbares Freigabesymbol:
Anhand des Symbols allein kann das Android-Framework es nicht für einen sehbehinderten Nutzer beschreiben. Das Android-Framework benötigt eine zusätzliche Textbeschreibung des Symbols.
Der Parameter contentDescription beschreibt ein grafisches Element. Verwenden Sie einen lokalisierten String, da er für den Nutzer sichtbar ist.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Einige grafische Elemente sind rein dekorativ und müssen dem Nutzer nicht mitgeteilt werden. Wenn Sie den Parameter contentDescription auf null festlegen, geben Sie dem Android-Framework an, dass diesem Element keine Aktionen oder kein Status zugeordnet sind.
@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 ist hauptsächlich für grafische Elemente wie Bilder vorgesehen. Material-Komponenten wie Button oder Text und ausführbare Verhaltensweisen wie clickable oder toggleable haben andere vordefinierte Semantiken, die ihr intrinsisches Verhalten beschreiben und über andere Compose-APIs geändert werden können.
Interaktive Elemente
Mit den Compose-APIs für Material und Foundation können UI-Elemente erstellt werden, mit denen Nutzer über die Modifier-APIs clickable und toggleable interagieren können. Da interaktive Komponenten aus mehreren Elementen bestehen können, werden die Semantiken der untergeordneten Elemente von clickable und toggleable standardmäßig zusammengeführt, sodass die Komponente als eine logische Einheit behandelt wird.
Ein Material Button kann beispielsweise aus einem untergeordneten Symbol und etwas Text bestehen. Anstatt die Kinder als Einzelpersonen zu behandeln, werden die Semantik der untergeordneten Elemente standardmäßig in einem Material
Button zusammengeführt, sodass sie von Barrierefreiheitsdiensten entsprechend gruppiert werden können:
Wenn Sie den Modifikator clickable verwenden, werden die Semantik der untergeordneten Elemente in einer einzelnen Entität zusammengeführt, die mit einer entsprechenden Aktionsdarstellung an Barrierefreiheitsdienste gesendet wird:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
Sie können auch einen bestimmten onClickLabel für das übergeordnete klickbare Element festlegen, um zusätzliche Informationen für Barrierefreiheitsdienste bereitzustellen und eine ansprechendere Darstellung der Aktion zu ermöglichen:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
Wenn wir TalkBack als Beispiel verwenden, würde dieser clickable-Modifikator mit seinem Klicklabel TalkBack ermöglichen, einen Aktionshinweis wie „Doppeltippen, um diesen Artikel zu öffnen“ anstelle des allgemeineren Standardfeedbacks „Doppeltippen, um zu aktivieren“ zu geben.
Dieses Feedback variiert je nach Art der Aktion. Bei einem langen Klick würde TalkBack den Hinweis „Doppeltippen und halten, um“ gefolgt von einem Label ausgeben:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
In einigen Fällen haben Sie möglicherweise keinen direkten Zugriff auf den clickable-Modifikator (z. B. wenn er in einer niedrigeren geschachtelten Ebene festgelegt ist), möchten aber trotzdem das Ankündigungslabel ändern. Dazu müssen Sie die Einstellung von clickable von der Änderung der Mitteilung trennen. Verwenden Sie dazu den Modifikator semantics und legen Sie dort das Klicklabel fest, um die Aktionsdarstellung zu ändern:
@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 } ) } ) }
Sie müssen die Klickaktion nicht zweimal durchlaufen. Vorhandene Compose-APIs wie clickable oder Button übernehmen das für Sie. Mit der Zusammenführungslogik wird geprüft, ob das äußerste Modifikatorlabel und die Aktion für die vorhandenen Informationen ausgeführt werden. Im vorherigen Beispiel übergibt NestedArticleListItem die Klickaktion openArticle() automatisch an die Semantik von clickable. Sie können die Klickaktion im zweiten Semantik-Modifier leer lassen. Das Klicklabel wird jedoch aus dem zweiten semantischen Modifikator onClick(label = "Open this document") übernommen, da es im ersten nicht vorhanden war.
Es kann vorkommen, dass untergeordnete Semantik nicht in eine übergeordnete Semantik zusammengeführt wird. Weitere Informationen finden Sie unter Zusammenführen und Bereinigen.
Benutzerdefinierte Komponenten
Wenn Sie eine benutzerdefinierte Komponente erstellen, sehen Sie sich die Implementierung einer ähnlichen Komponente in der Material-Bibliothek oder anderen Compose-Bibliotheken an. Ahmen Sie dann das Verhalten in Bezug auf die Bedienungshilfen nach oder passen Sie es entsprechend an. Wenn Sie beispielsweise das Material Checkbox durch Ihre eigene Implementierung ersetzen, werden Sie durch die vorhandene Checkbox-Implementierung daran erinnert, den Modifier triStateToggleable hinzuzufügen, der die Barrierefreiheitseigenschaften für die Komponente verarbeitet. Verwenden Sie außerdem Foundation-Modifikatoren, da diese integrierte Überlegungen zur Barrierefreiheit und bestehende Compose-Praktiken enthalten, die in diesem Abschnitt behandelt werden.
Ein Beispiel für eine benutzerdefinierte Schalterkomponente finden Sie auch im Abschnitt „Semantik festlegen und löschen“. Weitere Informationen zur Unterstützung der Barrierefreiheit in benutzerdefinierten Komponenten finden Sie in den API-Richtlinien.
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Bedienungshilfen in Compose
- Compose-Layout testen