zurück zum Artikel

Barrierefreiheit: Stolpersteine bei mobilen Anwendungen überwinden, Teil 2

Know-how
Barrierefreiheit: Stolpersteine bei mobilen Anwendungen überwinden, Teil 2

Der barrierefreie Zugang zu Apps ist wichtig. Allgemeine Designrichtlinien und konkrete Maßnahmen helfen bei der Umsetzung.

Im Frühjahr 2009 erschien die erste nach einer Süßspeise benannte Version des damals noch jungen mobilen Betriebssystems Android. Cupcake (Android 1.5) besaß noch keine Funktion zur barrierefreien Bedienung. Das änderte sich jedoch noch im gleichen Jahr mit der Veröffentlichung von Donut (Android 1.6) sowie Googles mobile Screenreader TalkBack. Damit hielt eine grundlegende Zugänglichkeit Einzug in Android, die kontinuierlich mit jeder neueren Version verbessert [1] und dokumentiert [2] wurde. Damit feiert der komfortable Weg, zugängliche Apps unter Android zu entwickeln, im Jahr 2019 zehnjähriges Jubiläum – eine gute Gelegenheit für einen Blick auf den Status quo.

Stolperfallen verhindern

Eine App unter Android zugänglicher zu gestalten, erfordert in der Regel keine größeren Umstrukturierungen des Quellcodes. Vielmehr gilt es, ähnlich wie bei der Unterstützung unterschiedlicher Displaygrößen [3] einige grundsätzliche Empfehlungen und Ergänzungen zu beherzigen – idealerweise ab dem Start der Entwicklung. Bereits kleine Anpassungen während des Erstellens der Layoutdateien haben einen großen positiven Effekt auf die Zugänglichkeit der App.

Barrierefreiheit: Stolpersteine bei mobilen Anwendungen überwinden

Allgemeine Designempfehlungen zum Gestalten zugänglicher Apps hat Google im Rahmen der Dokumentation zum Material Design [5] veröffentlicht. Im Folgenden stehen daher konkrete Maßnahmen für Entwickler nativer Apps auf Basis der offiziellen Richtlinien von Google [6] im Fokus. Die Codebeispiele konzentrieren sich vorwiegend auf die jeweils ausschlaggebenden XML-Attribute in den Layout-Ressourcen. Diese statischen Angaben sind zu wählen, wenn sich die Werte nicht zur Laufzeit der App ändern. Sollte sich das Aussehen der Bedienelemente beispielsweise durch Nutzerinteraktion dynamisch anpassen, gilt es, die jeweiligen Werte programmatisch zu setzen, um eine barrierefreie App-Bedienung zu gewährleisten. Die Beschreibung der XML-Attribute der View-Klasse [7] hilft dabei, die passende dynamische Methode schnell zu finden.

Beschriftung von Elementen

Um die Funktion eines Bedienelements über einen Screenreader zu vermitteln, sollten Entwickler dem Bedienelement eine aussagekräftige Beschriftung (Label) gegeben. Dabei müssen sie das Vorleseverhalten des Screenreaders berücksichtigen und eventuelle textuelle Redundanzen vermeiden. Die meisten Screenreader einschließlich TalkBack nennen automatisch den Elementtyp, sodass zum beispielsweise "Speichern" eine bessere Beschriftung als "Speicher-Button" ist. Darüber hinaus greift das gewohnte Wechseln der Ressourcen abhängig von der (Sprach-)Konfiguration des Geräts. Die üblichen Regeln zum Lokalisieren von Android-Apps [8] gelten somit auch für Beschriftungen im Interesse einer verbesserten Zugänglichkeit.

Eingabefelder

Bei einem Eingabefeld wie EditText lässt sich das Label folgendermaßen über den Hinweistext setzen (ab API-Level 1):

Statisch (XML):

<EditText
...
android:hint="@string/label" />

Dynamisch (Kotlin):

editText.hint = getString(R.string.label)
Text- und grafische Elemente

Bei einem Textelement wie TextView ist das Setzen eines Labels in der Regel nicht erforderlich, weil der Screenreader den angezeigten Text automatisch erfasst und wiedergibt. Umso wichtiger ist dafür eine klare und verständliche Ausdrucksweise.

Bei einem grafischen Element wie ImageView oder ImageButton lässt sich das Label – analog zum Alternativtext in HTML [9] – über eine zusätzliche Beschreibung setzen (ab API-Level 4):

Statisch (XML):

<ImageButton
...
android:contentDescription="@string/label" />

Dynamisch (Kotlin):

imageButton.contentDescription = getString(R.string.label)

Ausschluss grafischer Elemente

Grafische Elemente, die ausschließlich einen dekorativen Zweck erfüllen, sollten Entwickler als irrelevant für den Screenreader markieren. Das Vorgehen hängt vom minimal unterstützten API-Level der App ab und ist wie folgt möglich:

Statisch (XML):

<!-- ab API-Level 4... -->
<ImageView
...
android:contentDescription="@null" />

<!-- ...oder ab minimalem API-Level 16 -->
<ImageView
...
android:importantForAccessibility="no" />

Dynamisch (Kotlin):

// ab API-Level 4...
imageView.contentDescription = null

// ...oder ab minimalem API-Level 16
imageView.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_NO
Label-Elemente

Ab API-Level 17 lässt sich zudem definieren, dass ein Element als Label für ein anderes Element dienen soll:

Statisch (XML):

<TextView
...
android:text="@string/label"
android:labelFor="@id/input_field" />

<EditText
android:id="@+id/input_field"
... />

Dynamisch (Kotlin):

textView.labelFor = R.id.input_field
Gruppierung von Elementen

Logisch beziehungsweise inhaltlich zusammengehörige Elemente sollten gruppiert sein, sodass der Screnreader ihren Inhalt als zusammenhängende Einheit betrachtet und vorliest. Die Gruppierung lässt sich folgendermaßen über einen fokussierbaren Container in Form einer beliebige Unterklasse von ViewGroup erreichen:

<LinearLayout
...>

<RelativeLayout
android:id="@+id/group1"
...
android:focusable="true">

<TextView ... />

<TextView ... />

</RelativeLayout>

<RelativeLayout
android:id="@+id/group2"
...
android:focusable="true">

<TextView ... />

<TextView ... />

</RelativeLayout>

</LinearLayout>

Eine ViewGroup mit android:focusable="true" bildet demnach eine Einheit, die der Screenreader als Ganzes anspringt und die enthaltenen Elemente zusammenhängend vorliest. Für obigen Code fokussiert das Vorleseprogramm die erste Gruppe group1, liest deren Inhalt vor und setzt nach einer Nutzerinteraktion bei der zweiten Gruppe group2 seinen Dienst fort. Die einzelnen Kindelemente (hier die TextViews) sind dabei nicht mehr direkt fokussier- beziehungsweise ansteuerbar. Das bedeutet für die Nutzer weniger Navigationsaufwand und erspart ihnen zudem unnötige Pausen beim Erfassen von wichtigen, zusammengehörigen Informationen.

Ein Hinweis sei noch angebracht: android:focusable wirkt sich auf die Navigationsreihenfolge bei Nutzung von Eingabehardware wie einer Tastatur aus. Daher lässt sich ab Android 9 Pie (API-Level 28) das nur für Screenreader gültige android:screenReaderFocusable anstelle von android:focusable in Situationen benutzen, in denen Letzteres unerwünschte Seiteneffekte bei der Navigation hätte.

Gerichtete Navigation

Neben Touch-Steuerung bietet Android weitere Eingabemethoden an. Nutzer können unter anderem Hardware wie eine Tastatur oder ein Steuerkreuz anschließen. Insbesondere erlaubt Android Eingabemethoden, die eine barrierefreie Bedienung ermöglichen. Dazu zählen Sprach- [10] und Schaltersteuerung [11], die bei motorischen Einschränkungen eingesetzt werden können.

Um eine App für alternative Bedienungsweisen zu rüsten, ist es wie in HTML [12] wichtig, eine gerichtete Navigation sicherzustellen. Standardmäßig verhält sich Android so, dass es fokussierbare Elemente in der Reihenfolge anspringt, in der sie im Layout angeordnet sind. Häufig genügt das für eine angemessene Navigation, aber es gibt Situationen, in denen Entwickler die Navigation explizit durch Festlegen des Fokuswechsels korrigieren müssen.

Bei der Vorwärtsnavigation geht der Fokus beispielsweise durch Drücken der Tab-Taste einer Tastatur an das jeweils nachfolgende Element weiter. Um den Nachfolger festzulegen, lässt sich das Attribut android:nextFocusForward oder die Methode setNextFocusForwardId(int) verwenden:

<RelativeLayout
...>

<Button
android:id="@+id/button1"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:nextFocusForward="@+id/editText"
... />

<Button
android:id="@+id/button2"
android:layout_below="@id/button1"
android:nextFocusForward="@+id/button1"
... />

<EditText
android:id="@id/editText"
android:layout_alignBottom="@+id/button2"
android:layout_toLeftOf="@id/button2"
android:nextFocusForward="@+id/button2"
... />

</RelativeLayout>

Die Fokusreihenfolge geht damit von button1 zu editText, zu button2, was gleichzeitig der visuellen Anordnung entspricht. Ohne das Setzen von android:nextFocusForward würde der Screenreader die Reihenfolge der Elemente im Layout verwenden: button1 zu button2 zu editText.

Bei der unter anderem durch die Pfeiltasten einer Tastatur ausgelösten Richtungsnavigation geht der Fokus an das jeweils in einer bestimmten Richtung liegende Element weiter. Um das Element festzulegen, das den Fokus für die jeweilige Richtung erhalten soll, lassen sich die Attribute android:nextFocusUp, android:nextFocusDown, android:nextFocusLeft und android:nextFocusRight beziehungsweise die Methoden setNextFocusUpId(int), setNextFocusDownId(int), setNextFocusLeftId(int) und setNextFocusRightId(int) verwenden.

<Button
android:id="@+id/button1"
android:nextFocusRight="@+id/button2"
android:nextFocusDown="@+id/editText"
... />

<Button
android:id="@id/button2"
android:nextFocusLeft="@id/button1"
android:nextFocusDown="@id/editText"
... />

<EditText
android:id="@id/editText"
android:nextFocusUp="@id/button1"
... />

Ausgehend von button1 geht eine Rechtsnavigation zu button2, umgekehrt führt eine Linksnavigation von button2 zu button1. Eine Navigation von einem der Buttons nach unten fokussiert editText, und von dort geht es zu button1, sobald der Nutzer hochnavigiert.

Zugängliche benutzerdefinierte Views

Manchmal reichen die gegebenen UI-Komponenten für die Umsetzung der Projektanforderungen nicht aus, sodass eine benutzerdefinierte View-Klasse, eine sogenannte Custom View, erforderlich ist, die Entwickler ebenfalls zugänglich gestalten sollten. Die hauptsächliche Arbeit besteht darin, spezielle API-Methoden im Interesse der Barrierefreiheit zu implementieren – allen voran sendAccessibilityEvent(int) und onPopulateAccessibilityEvent(AccessibilityEvent). Zusätzliche Informationen finden sich in der offiziellen Dokumentation [13] und der Beispielimplementierung [14].

Probieren geht über Studieren

Am anschaulichsten können Entwickler eine App auf Barrierefreiheit testen, indem sie sie mit unterschiedlichen Bedienungshilfen benutzen. Es empfiehlt sich daher für Entwickler, den mittlerweile zur Android Accessibility Suite gehörenden [15] Screenreader TalkBack (oder Voice Assisant [16] bei neueren Samsung-Geräten) über die Systemeinstellungen Bedienungshilfen zu aktivieren. Die Übungslektionen, die beim ersten Aktivieren erscheinen und auch danach noch zur Verfügung stehen, helfen dabei, ein Gefühl für die Benutzung eines mobilen Screenreader zu bekommen. Nach einem kurzen Moment der Gewöhnung an die Bedienung mittels Screenreader steht dem Test der eigenen App auf Herz und Nieren nichts mehr im Wege. Weiterhin sollten Entwickler und Tester verifizieren, ob ihre App auch mit veränderter Schrift- und Anzeigegröße [17] noch hinreichend gut bedienbar ist.

Selbstverständlich liefern nicht zuletzt Benutzertests wertvolle Einblicke und damit nicht zu unterschätzendes Feedback zu Hürden in der zugänglichen Benutzerführung. Neben dem manuellen Testen gibt es automatisierte Tools, die eine App auf Barrierefreiheit überprüfen.

Analyse mit Lint

Mit Lint [18] bietet der Android-Werkzeugkasten eine Anwendung, um frühzeitig Programmierfehler und Unzulänglichkeiten aller Art im Projekt mit statischer Code-Analyse zu identifizieren. Dazu zählen einige Mängel bei der Barrierefreiheit: Layoutelemente zu finden, bei denen das contentDescription-Attribut fehlt, ist beispielsweise für Lint ein Leichtes.

Die Analyse lässt sich in Android Studio über den Menüpunkt Analyze | Inspect Code ausführen. Die Ergebnisse zeigt die IDE anschließend im Bereich Inspection Results unter Android | Lint | Accessibility an.

Alternativ lässt sich die Analyse über die Kommandozeile mit dem Gradle-Wrapper im Projekt-Wurzelverzeichnis starten:

./gradlew lint

Android Studio generiert anschließend einen Lint-Bericht und gibt die Pfade zu der XML- und der HTML-Version aus.

Accessibility Scanner

Die Google-App Accessibility Scanner [19] gibt durch den Scan von Benutzeroberflächen Empfehlungen zur Verbesserung der Barrierefreiheit. Sie ist als Bedienungshilfe implementiert und wie der Screenreader über eine passende Systemeinstellung zu aktivieren. Konkret analysiert die App folgende Punkte:

Weitere Details zur Benutzung und zur Auswertung der Ergebnisse sind auf der Hilfsseite des Tools [20] zu finden.

Node Tree Debugging

Werkzeuge für Barrierefreiheit wie Screenreader haben eine eigene Sicht auf die Benutzeroberfläche einer App. Das in TalkBack enthaltene Node Tree Debugging [21] bietet eine Ansicht auf die Hierarchie und die Attribute von Bedienelementen aus der Perspektive der Werkzeuge. Es ermöglicht, die Baumstruktur eines App-Screens als Log auszugeben. Wie das genau funktioniert und wie die Ergebnisse zu interpretieren sind, ist in der Anleitung detailliert beschrieben.

Espresso

Das Framework Espresso ermöglicht das Schreiben automatisierter Benutzeroberflächentests. Bestehende Tests lassen sich ohne viel Aufwand um eine Überprüfung auf Mängel in der Barrierefreiheit erweitern. Folgender Code – mit aktualisierter import-Anweisung – in der Initialisierungsmethode eines Espresso-Tests konfiguriert ihn auf das Überprüfen der Barrierefreiheit einer View bei jeder Interaktion über ViewAction.

import 
androidx.test.espresso.accessibility.AccessibilityChecks

@RunWith(AndroidJUnit4::class)
@LargeTest
class AccessibilityChecksIntegrationTest {
companion object {
@BeforeClass @JvmStatic
fun enableAccessibilityChecks() {
// aktiviert die zusätzlichen Checks zur Barriefreiheit
AccessibilityChecks.enable()
}
}
}

Fortschritte und Empfehlungen

In den letzten zehn Jahren gab es deutliche Fortschritte für die Barrierefreiheit unter Android, und jede neue Version des mobilen Betriebssystems bringt weitere Verbesserungen in dem Bereich [22]. Neben einem auf Zugänglichkeit ausgelegtem App-Design ist das Beherzigen simpler Empfehlungen und Anpassungen mit vergleichsweise geringem Aufwand während der Entwicklung der Layout-Dateien bereits die halbe Miete zur barrierenfreien App. Wichtig sind die sinnvolle Beschriftung von Elementen, die Gruppierung zusammengehöriger Komponenten sowie das Anpassen der Navigation für Screenreader beziehungsweise Eingabehardware.

Damit App-Designer und -Entwickler eine Vorstellung haben, mit welchen Herausforderungen Menschen mit Einschränkungen bei der Bedienung mobiler Apps zu kämpfen haben, sei ihnen ans Herz gelegt, ihre Anwendungen mit den unter Android zur Verfügung stehenden Bedienungshilfen ausgiebig zu testen. Der Perspektivwechsel hilft, Schwachstellen in der Zugänglichkeit schnell zu identifizieren und zu beheben.

Für Entwickler lassen sich allgemeine Empfehlungen folgendermaßen zusammenfassen:

  1. Keep it simple: einfache Struktur der App, Kernfunktionen klar priorisieren und eindeutig benennen,
  2. auf Lesbarkeit wie Schriftgröße und Kontrast achten – nicht nur für Sehbeeinträchtigte,
  3. flexibles Auto-Layout benutzen, sodass Elemente bei der Schriftvergrößerung nicht verrutschen oder das Layout verzerren,
  4. alle Navigationselemente, Schaltflächen und Bilder für die Sprachausgabe mit eindeutigen Texten hinterlegen und
  5. per Spracheingabe alle Funktionen steuerbar und alle Inhalte durchsuchbar machen. (rme [23])

Roman Zimmer
arbeitet bei adesso mobile solutions als Senior Software Engineer. Neben der Beratung und Realisierung von Full-Stack-Projekten aller Art ist er seit 2011 leidenschaftlicher Android-Entwickler.

Alexander Huber
arbeitet als Android-Entwickler bei adesso mobile solutions am Standort Berlin.

Martin Kinting
ist Niederlassungsleiter der adesso mobile solutions am Standort Berlin und Senior Sales Manager unter anderem in den Bereichen Banking und Life Science.


URL dieses Artikels:
http://www.heise.de/-4500303

Links in diesem Artikel:
[1] https://accessibleandroid.wordpress.com/2013/08/02/a-brief-history-of-android-accessibility/
[2] https://android-developers.googleblog.com/2012/04/accessibility-are-you-serving-all-your.html
[3] https://developer.android.com/training/multiscreen/screendensities
[4] https://www.heise.de/developer/artikel/Barrierefreiheit-Stolpersteine-bei-mobilen-Anwendungen-ueberwinden-Teil-1-4476673.html
[5] https://material.io/design/usability/accessibility.html
[6] https://developer.android.com/guide/topics/ui/accessibility
[7] https://developer.android.com/reference/android/view/View.html#xml-attributes_1
[8] https://developer.android.com/guide/topics/resources/localization
[9] https://webaim.org/techniques/alttext/
[10] https://support.google.com/accessibility/android/answer/6151848
[11] https://support.google.com/accessibility/android/answer/6122836
[12] https://webaim.org/techniques/keyboard/
[13] https://developer.android.com/guide/topics/ui/accessibility/custom-views
[14] https://github.com/googlesamples/android-BasicAccessibility/blob/master/Application/src/main/java/com/example/android/basicaccessibility/DialView.java
[15] https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback
[16] https://www.samsung.com/uk/support/mobile-devices/how-do-i-enable-and-disable-voice-assistant-talkback-on-my-samsung-galaxy-smartphone/
[17] https://support.google.com/accessibility/android/answer/6006972?hl=en
[18] https://developer.android.com/studio/write/lint
[19] https://play.google.com/store/apps/details?id=com.google.android.apps.accessibility.auditor
[20] https://support.google.com/accessibility/android/topic/6376582
[21] https://developer.android.com/guide/topics/ui/accessibility/node-tree-debugging
[22] https://developer.android.com/about/versions/pie/android-9.0#a11y
[23] mailto:rme@ct.de