Einige Hinweise zur Erstellung Barrierefreier Programmoberflächen am Beispiel von C# und WPF
Geschrieben von Eric Scheibler am 22.11.2011
Ich arbeite an der TU Dresden als studentische Hilfskraft. Derzeit läuft die Lehrveranstaltung “Barrierefreie Dokumente”. Alle zwei Wochen bekommen die Studenten eine Aufgabe, die sie dann bearbeiten und rechtzeitig abgeben müssen. In der ersten Übung ging es um die prototypische Implementation einer barrierefreien programmoberfläche. Das Programm soll einem einfachen VoiceOverIP Client nachempfunden sein. Das Hauptfenster besteht aus einem Eingabefeld für die Rufnummer und 15 Buttons für die Nummerneingabe und die weitere Bedienung. Zusätzlich soll noch ein modaler Dialog für die Übernahme einer Telefonnummer in das Adressbuch erstellt werden.
Nach der Korrektur der abgegebenen Lösungen habe ich eine Liste mit sehr häufig vorkommenden Problemen und daraus resultierenden Hinweisen erstellt, die ich im Folgenden vorstellen möchte. Dabei ist mir aufgefallen, dass sich die Fehler keinesfalls nur auf die Barrierefreiheit beziehen sondern in einem erheblichen Maße auch allgemeine Usability Probleme darunter sind. Da die Anwendung in C# unter Verwendung von Windows Presentation Foundation (WPF) erstellt werden sollte, werde ich bei konkretem Code auf die Implementation in C# eingehen. Die meisten Dinge sollten jedoch von universeller Natur sein und sich somit in allen Programmiersprachen umsetzen lassen.
Inhaltsverzeichnis
- 1. Korrekte Beschriftung der Oberflächenobjekte
- 2. Navigation innerhalb der Programmoberfläche
- 3. Self Voicing: Eigene Sprachausgabe definieren?
- 4. Weitere Empfehlungen
- 5. Test der fertigen Oberfläche
- 6. Anmerkungen
Zunächst in Kurzform die Hauptanforderungen an eine solche barrierefreie Programmoberfläche:
- Alle Steuerelemente benötigen eine Beschreibung und müssen mit der Tastatur zugänglich sein
- Bei der Vergrößerung der Programmoberfläche muss die Schrift proportional mit skalieren
- Die Oberfläche sollte einem logischen Aufbau folgen und übersichtlich gestaltet werden
- Bei der Farbauswahl muss auf genügend große Kontraste geachtet werden
- Das Programm muss auch mit einem anderen Kontrastschema bedienbar sein. Als Beispiel sei das Schema “Weiße Schrift auf schwarzem Grund” genannt, welches besonders von blendempfindlichen Nutzern verwendet wird.
- Intuitiv verwendbare Shortcuts unterstützen den Nutzer bei der Navigation mittels Tastatur. Dies betrifft sowohl blinde als auch motorisch behinderte User.
Korrekte Beschriftung der Oberflächenobjekte
Dies ist einer der wichtigsten Punkte für Screenreader Nutzer. Haben die einzelnen Bedienelemente keine Beschreibung so ist das Programm zumindest für einen blinden Benutzer nahezu unbedienbar. Im Falle des VoiceOverIP Clients bekäme der User beim Durchgehen der Objekte dann lediglich 15 mal “schalter” bzw. “Button” zu hören / lesen da der Screenreader von der Oberfläche jeweils nur den Typ des gerade fokusierten Objekts geliefert bekommt. Damit wäre das Eingeben einer Telefonnummer nicht möglich.
Es gibt mehrere Möglichkeiten, dem Screenreader die Beschreibung des Elements zukommen zu lassen. Diese unterscheiden sich auch von Objekt zu Objekt. Arbeitet man mit C# und WPF, dann sollte man sich die Member der Klasse AutomationProperties anschauen und dort im Speziellen AutomationProperties.Name und AutomationProperties.HelpText (siehe AutomationProperties Class).
Diese beiden Atribute sollten von jedem aktuellen Screenreader ausgewertet werden. Getestet habe ich’s mit NVDA Version 2011.2. Nehmen wir als Beispiel die Textbox für die Nummerneingabe, welche meist in der Datei MainWindow.xaml zu finden ist.
Fügt man die obigen Atiribute der Textbox hinzu, so schaut dies etwa so aus:
<TextBox Name="textBox1" AutomationProperties.Name="Telefonnummer" AutomationProperties.HelpText="Bitte eine Telefonnummer eingeben" ... />
Beim Fokusieren der Textbox würde NVDA nun nicht mehr wie zuvor nur “Eingabefeld” sondern “Telefonnummer Eingabefeld [kurze Sprechpause] Bitte eine Telefonnummer eingeben” sprechen. Die Atribute sind aber offenbar nicht bei Microsofts Visual Studio im GUI Editor für die Erstellung grafischer Oberflächen zu finden und müssen daher in der xaml Datei manuell eingetragen werden.
Ich habe auch öfter diese Lösung gesehen:
<TextBox Name="textBox1" ToolTip="Telefonnummer" ... />
NVDA verarbeitet dies zu “Eingabefeld Telefonnummer”. Das funktioniert bedingt, weil der Screenreader auch das ToolTip Atribut abfragt. Trotzdem ist dies keine saubere Lösung und sollte nicht verwendet werden, da der ToolTip dafür nicht geschaffen wurde und ihn nicht jeder Screenreader standardmäßig nutzt.
manche Objekte bringen noch weitere auslesbare Atribute mit. Beispiel: Button.
<Button Content="Call" Name="button2" AutomationProperties.Name="Call" AutomationProperties.HelpText="Wählt die eingegebene Nummer" ... />
NVDA kann sowohl auf Content wie auch auf AutomationProperties.Name zugreifen, bevorzugt aber wenn vorhanden immer AutomationProperties.Name. Daher sollte man beiden Atributen im Normalfall den gleichen Wert zuweisen. Content kann allerdings nur ausgewertet werden, wenn es einen einfachen String enthält. Innerhalb des Atributs beispielsweise noch einen Textblock zu definieren, welcher dann die Beschriftung des Buttons darstellt, ergibt eine für Screenreader nicht mehr auslesbare Verschachtelung. Fehlt zusätzlich noch AutomationProperties.Name so ist der Inhalt des Buttons erneut nicht zugänglich.
Ob man AutomationProperties.HelpText benötigt, lässt sich oft nur im Einzelfall entscheiden. In der Regel braucht man ihn nur, wenn sich die Funktion des Steuerelements weniger über die Beschriftung als mehr über einen visuell dargestellten Zusammenhang erschließt. In der obigen Textzeile wäre ein solcher Hilfetext eher nicht nötig, da der Screenreader den Nutzer bereits mit Informationen über die Bedienung von Standardelementen informiert. Man sollte in Helptext auch nicht das Gleiche reinschreiben wie in Name. Anderenfalls würde der Screenreader je nach Konfiguration zwei Mal das Gleiche sprechen. Außerdem ists retundant. Fällt euch also kein passender bzw. hilfreicher Kommentar ein, so lasst HelpText einfach weg.
Nützlich ist ebenso AutomationProperties.IsRequiredForForm um z.B. im Kontaktspeicherdialog das Eingabefeld für den nachnamen als Pflichtfeld zu kennzeichnen.
Navigation innerhalb der Programmoberfläche
Die üblichen Möglichkeiten der Tastaturnavigation sind:
- Tab und Shift + Tab: Bewegt den Fokus zum nächsten / vorherigen Steuerelement, dessen Tabindex > 0 ist
- Druck auf die Alt - Taste: Springt ins Menü (sofern vorhanden)
- Pfeiltasten: Navigation beispielsweise im Ziffernblock in allen vier Richtungen
- Space oder Enter: Auslösen einer Aktion, z.B. Drücken eines Buttons
- Weitere System - oder Programmshourtcuts, z.B. ESC und Alt + F4
Die Tabreihenfolge sollte sich am logischen Programmaufbau orientieren und nur in Ausnahmefällen davon abweichen. Ein meiner Meinung nach ungünstiges Beispiel wäre: Vertauschen von Tabindex bei den Buttons “0” und “”, sodass der Fokus nach Verlassen der ”9” gleich auf die ”0” und danach erst auf ”” und “#” springt. Dies läuft der Erwartungshaltung des Nutzers entgegen (bekannter Aufbau einer Telefontastatur) und kann zu Inkonsistenzen bei der Navigation führen (Tab vs. Pfeiltasten). Sowas sollte man sich also wirklich gut überlegen und wenn mans selbst für angebracht hält, von Nutzern testen lassen.
Auch ein Menü sollte selbst bei kleinen Anwendungen bereitgestellt werden. Das Menü listet alle möglichen Benutzeraktionen geordnet auf und gibt somit einen guten Überblick über die Programmfunktionen ohne das die gesamte Oberfläche durchsucht werden muss. Dabei sollte aber darauf geachtet werden, dass das Menü nicht in der Standardtabreihenfolge auftaucht und damit während der Navigation innerhalb der GUI nicht angesprungen wird. Hinein kommt der Nutzer bereits mit einem Druck auf die Alt - Taste. Optimal ist es, wenn auch die einzelnen Reiter direkt angewählt werden können also Alt + d für das Datei, Alt + b für das Bearbeiten Menü usw.
Bei der Umsetzung der Tastaturnavigation sollte man sich möglichst an die allgemein gültigen Konventionen halten. So wird ein modaler Dialog immer mit ENTER beendet und mit ESC abgebrochen und die Hilfe durch Drücken auf F1 angezeigt. Solche Standards nicht zu implementieren oder gar mit eigenen Befehlen zu überschreiben erschwert allgemein die intuitive Nutzung.
Selbst hinzugefügte Shortcuts können ebenfalls die Bedienung vereinfachen. Im vorliegenden Beispiel bietet es sich an, die Telefonnummer nicht nur durch das Anklicken der Buttons sondern auch durch den Nummernblock auf der Tastatur eingeben zu können. Dies erreicht man am einfachsten mit einem KeyEventHandler. Weitere sinnvolle wären:
- c: Call
- s: Save contact
- F6: Fokus springt ins Nummerneingabefeld
Weniger nützlich hingegen wäre z.B. u = call oder F3 = save, da sie erheblich schwerer zu merken sind. Ferner gilt: Je weniger Steuertasten (CTRL, Alt,, Shift) desto einfacher ist die Tastkombination zu betätigen. Im obigen Beispiel kann sogar gänzlich auf die Steuertasten verzichtet werden, da die Anwendung lediglich ein Eingabefeld enthält, in das keine Buchstaaben eingetragen werden dürfen. So kommt es zu keinen Konflikten. F6 wurde gewählt, da diese Taste bei vielen Programmen genutzt wird, um zwischen verschiedenen Bereichen einer Anwendung zu wechseln.
Ein Shortcut sollte in verschiedenen Dialogen immer die gleiche Aktion ausführen also nicht s = send in Fenster 1 und s = save in Fenster 2.
Self Voicing: Eigene Sprachausgabe definieren?
Mehrere Übungsteilnehmer waren der Meinung, dass es insbesondere für blinde Nutzer nicht genügen würde, die grafische Oberfläche anzupassen. Sie schlugen daher vor, zusätzlich eine eigene Sprachausgabe in die Programmoberfläche zu integrieren. Mit der Sprachausgabe sollten dann zusätzliche Erläuterungen gegeben werden. Dies mag aus der Sicht eines Benutzers ohne Screenreader Erfahrung zunächst einmal eine vielversprechende Idee darstellen, ist aber aus mehreren Gründen abzulehnen:
- Die Sprachausgabe kollidiert mit der des Screenreaders. Dies lässt sich gar nicht vermeiden.
- Einfache Soundsamples sind eher hinderlich: Sie können vom Nutzer nicht abgebrochen werden (man denke an einen langen Hilfetext, welcher bei jedem Fokusieren immer wieder komplett abgespielt wird), die Geschwindigkeit der Spraachausgabe ist nicht regelbar und zumeist wird so nur eine Sprache unterstützt. Soll Self Voicing also für den Nutzer gewinnbringend umgesetzt werden, so ist viel Zeit und Wissen über die Funktion eines Screenreaders von Nöten.
- Welche Anweisungen sollten gesprochen werden? Alles? Dann wäre der Aufwand noch größer und außerdem retundant, denn dann würde man einen eigenen Screenreader bauen. Nur Hilfetexte? Was zählt dann darunter? Wie geht man auf Nutzer mit unterschiedlichem Computerkenntnissen ein?
- Ziel sollte es sein , eine barrierefreie Anwendung zu erstellen d.h. ein Programm, welches alle unabhännig von ihrer Behinderung benutzen können. Je mehr Sprachausgabe man integriert desto mehr würde die Anwendung zu einer Speziallösung für Blinde, was dem eigentlichen Ziel widerspricht. Außerdem: Speziallösung = teuer und das erste, was bei zukünftigen Releases nicht weiterentwickelt wird. Eine ähnliche Situation gab es vor einigen Jahren mit speziellen Textversionen von Webseiten für Blinde. Diese waren im Funktionsumfang oft eingeschränkt und nicht selten im Vergleich zur “normalen” Version veraltet.
Insbesondere das oben bereits diskutierte Atribut “AutomationProperties.HelpText” sollte für die zusätzlichen Hilfetexte geeignet sein. Zusätzlich kann eine Hilfedatei angeboten werden. Hat man dies alles umgesetzt, so kann davon ausgegangen werden, dass ein blinder Benutzer mittels Screenreader in der Lage ist, das Programm zu bedienen. Auch die Brailledarstellung wird vollständig vom Screenreader bereitgestellt, darum braucht man sich als Anwendungsentwickler ebenfalls keine Gedanken zu machen.
Weitere Empfehlungen
- Beim Betreten eines neuen Dialoges sollte der Tastaturfokus gleich auf einem sinnvoll gewählten Steuerelement liegen. So könnte er sich im Speichern Dialog gleich im ersten Eingabefeld befinden.
- Auch mit Sounds kann man eine getätigte Nutzerinteraktion bestätigen, Beispiel: ein dezentes Geräusch beim erfolgreichen Abspeichern eines Kontakts. Aber auch dies sollte man nicht übertreiben. Ein “beep” bei jedem Fokuswechsel wirkt störend und dürfte keinem so recht gefallen.
- Ein Cancel Button gehört zu jedem modalen Dialog.
- Alle Elemente mit denen interagiert werden soll müssen nicht nur vom richtigen Typ sondern auch fokusierbar sein. Ich habe beispielsweise eine Lösung bekommen, bei der das Feld für die Telefonnummer ein nicht antabbares Textlabel war. Somit wird das Erfassen der eingegebenen Rufnummer für einen blinden Benutzer deutlich erschwert. Alles, was mit dem Fokus nicht erfasst werden kann, ist schwieriger bis gar nicht auslesbar. Da man aber fast jedem Element einen Tabindex zuweisen kann, hätte dies dem Textlabel gut getan. Obgleich ein antabbares Eingabefeld in diesem Fall doch die bessere Wahl gewesen wäre.
- Um die Oberfläche während des Skalierens nicht versehentlich zu sehr schrumpfen zu können sollte eine relative Minimalgröße festgelegt werden.
Test der fertigen Oberfläche
Hat man seine Anwendung erstellt, ist es oft von Vorteil, selbst einen kurzen Test auf Barrierefreiheit durchzuführen.
Den Screenreader part prüft man am besten mit NVDA(NonVisual Desktop Access), welcher von www.nvda-project.org/ heruntergeladen werden kann. NVDA ist kostenlos und wird u.A. als portable Version angeboten, die auch von einem USB Stick aus startbar ist. Im Grunde genügt es bereits wenn bei dem Test einmal alle Steuerelemente mit der Tab Taste angesprungen werden. Dabei ist auf den Output der Sprachausgabe zu achten. Wem dies schwer fällt, kann im NVDA Menü (Capslock / Einfügen + n) unter Extras den Sprachbetrachter aktivieren. Zusätzlich sollte in diesem Schritt ermitteltwerden, ob das Programm komplett mit der Tastatur bedient werden kann indem u.A. alle definierten Shortcuts überprüft werden.
Als zweites testet man die GUI mit einem anderen Kontrastschema auf ihre Lesbarkeit. Man kann dies z.B. mit dem “Kontrast schwarz” Schema tun welches bei Windows XP in der Systemsteuerung unter Eingabehilfen im Tab Anzeige und unter Windows 7 mit einem Rechtsklick auf dem Desktop > anpassen aktiviert werden kann. Ist sämtlich vorhandener Text, insbesondere jener in Eingabefeldern, nach wie vor deutlich lesbar, dann ist alles in Ordnung.
Schließlich nimmt man noch die Windows Lupe zur Hilfe und überprüft damit die Übersichtlichkeit der erstellten GUI unter Verwendung eines höheren Zoomfaktors. Die Lupe ist in Windows unter Zubehör –> Eingabehilfen zu finden.
Anmerkungen
Viele Punkte habe ich anhand des konkreten Beispielprogramms aus der übung erläutert weil ich der meinung bin, dass so einiges einfacher nachvollziehbar wird. Die Liste erhebt nicht den Anspruch auf Vollständigkeit und einige Punkte sind sicherlich auch von subjektiver Natur. Auch können nicht alle Tipps eins zu eins in die Erstellung einer anderen Anwendung übernommen werden. Trotzdem denke ich, dass die Zusammenstellung dem Einen oder Anderen von Nutzem sein kann. Ergänzungen und Hinweise nehme ich gern entgegen und baue sie mit in den Text ein.