Frontend und Sehbehinderung: Ein Widerspruch?

Das Entwicklerteam der App SBB Inclusive zeigt anhand praktischer Beispiele, wie Hindernisse zur Barrierefreiheit einer App überwunden bzw. zum Vornherein vermieden werden können. Interessierte können sich gleich den entsprechenden Beispielcode für die Frameworks «Flutter» und «swiftUI» anzeigen lassen.

Drei praktische Empfehlungen zu einem inklusiven Frontend vom Entwicklungsteam der App «SBB Inclusive»

Im Dezember 2020 hat die SBB die App SBB Inclusive veröffentlicht. Der ursprüngliche Ansatz von SBB Inclusive war, die optische Kundeninformation an Bahnhöfen und in Fernverkehrszügen der SBB zu digitalisieren und auf dem persönlichen Smartphone der Kund:innen auszugeben. Dadurch wurden diese fürs Reisen essenziellen Informationen auch für Menschen mit einer Sehbehinderung les-, respektive hörbar. Seither wurde SBB Inclusive um zusätzliche Funktionen erweitert: Es gibt einen Türknopffinder, die Kundeninformationen von Tram- und Bushaltestellen wurden in die App integriert und die Durchsagen am Bahnhof werden in der App in Textform angezeigt. Deshalb wird die App auch zunehmend von Menschen mit einer Hörbehinderung verwendet und etabliert sich generell als Reisebegleiterin für Menschen mit einer Behinderung. SBB Inclusive wurde bereits mehrfach ausgezeichnet. So etwa 2020 mit dem Canne Blanche des SZBLIND oder dem Participants Award bei den UIC International Sustainable Railway Awards 2022. Als erste App überhaupt wurde SBB Inclusive 2022 durch die Stiftung «Zugang für alle» zertifiziert.

Doch welche Überlegungen braucht es im Frontend, damit eine App auch für Menschen mit einer Sehbehinderung einfach benutzbar ist? Eine interessante und gleichzeitig herausfordernde Aufgabe. Das Entwicklungsteam von SBB Inclusive hat in den vergangenen vier Jahren viel gelernt: Von den Testnutzenden mit einer Sehbehinderung, aber auch aus den eigenen Tests mit verschiedenen assistierenden Funktionen. Die drei wichtigsten Empfehlungen werden folgend vorgestellt und mit Beispielen aus dem Code illustriert:

Empfehlung 1: Unterstütze vergrösserte Inhalte.

Abgeschnittene Texte lassen sich einfach vermeiden

Viele Nutzer:innen mit einer Sehbehinderung nutzen die Möglichkeit des Betriebssystems, den Text zu vergrössern. Daher ist es wichtig, die verschiedenen Inhaltsgrössen zu unterstützen.

Beim Testen einer App mit vergrösserten Texten kommt es immer wieder vor, dass einige Inhalte abgeschnitten werden. In den meisten Fällen ist dies leicht zu beheben, indem die App die Anzeige von mehrzeiligen Texten zulässt.

SwiftUI

Text("...")
    .fixedSize(horizontal: false, vertical: true)

Flutter

// Flutter
Text(‘…’), // it usually just works ¯\_(ツ)_/¯
// but use Expanded for Text in a Row
Row(
    children: <Widget>[
        Expanded(
            child: Text(‘…’),
        ),
    ],
)

Manchmal, etwa bei Buttons, ist dies jedoch nicht wünschenswert. Deshalb ist es einerseits sinnvoll, möglichst kurze Beschriftungstexte zu wählen und andererseits – als Kompromiss – die maximale Schriftgrösse für bestimmte Texte einzuschränken und die Darstellung dem Betriebssystem zu überlassen. Für Menschen mit einem reduzierten Sehvermögen ist eine Beschränkung der Schriftgrösse jedoch nicht ideal, da der Text in einer für sie zu kleinen Schrift angezeigt werden könnte. Es empfiehlt sich deshalb, wo immer möglich Beschriftungen zu verkürzen, Buttons im Design anders anzuordnen oder mehrzeilige Inhalte zuzulassen.

SwiftUI

Text(“…”)
    .minimumScaleFactor(0.1)

Flutter

AutoSizeText(    // Use this awesome plugin
    '...',
    maxLines: 1,
    minFontSize: 1,
)
Auf dem Bild sind drei Handybildschirme von SBB Inclusive abgebildet. Die ersten beiden Bildschirme zeigen die Ansicht im Tab «Unterwegs». Auf den linken Bildschirm werden zu lange Texte durch drei Punkte abgeschnitten. Im zweiten Bildschirm wird es korrekt dargestellt: Die App lässt mehrzeilige Texte zu. Auf dem dritten Bild ist der Tab «Bahnhof» abgebildet. Dort werden die Texte in den Buttons verkleinert dargestellt, damit sie in den Buttons nicht umgebrochen werden.
Abbildung 1: Abgeschnittener Text (links), Text mit mehreren Zeilen (Mitte), Text mit Grössenbeschränkung in Buttons (rechts).

Eine Vergrösserung von Texten bedeutet in vielen Fällen, dass nicht mehr der gesamte Text auf einem Bildschirm Platz findet. Nutzer:innen mit einer Sehbehinderung sind sich eine solche Darstellung gewohnt. Wenn ein Text bei starker Vergrösserung über mehrere Zeilen laufen könnte, wird deshalb die Verwendung von ScrollViews empfohlen.

Auf dem Bild werden zwei Bildschirme aus dem Onboarding von SBB Inclusive abgebildet. Auf dem ersten Bildschirm sind Bild und Text aus dem Onboarding-Rundgang in Standardgrösse abgebildet. Im zweiten Bildschirm wird derselbe Bildschirm mit einer starken Vergrösserung abgebildet. Dabei wird einerseits das Bild verkleinert und andererseits der Text unter dem Bild stark vergrössert. Weil nicht der gesamte Text auf dem Bildschirm Platz hat, braucht es eine Scrollview.
Abbildung 2: Mit ScrollViews finden auch bei erhöhter Textgrösse alle Inhalte Platz.

Andere Anordnung von Elementen für vergrösserte Inhalte

Leider funktionieren auch die einfachsten Designs nicht immer für alle Textgrössen. In diesen Fällen lohnt sich die Gestaltung eines alternativen Layouts, bei dem sich die Anordnung der Elemente je nach Grösse des Inhalts verändert. So kann es beispielsweise sinnvoll sein, Icons auszublenden, um mehr Platz für wichtigere Informationen zu schaffen.

SwiftUI

@Environment(\.sizeCategory) var sizeCategory

if SizeCategories.accessibility.contains(sizeCategory) {
    TrainConnectionRowAccessibility(…)
} else {
    TrainConnectionRowNormal(…)
}

Flutter

final mq = MediaQuery.of(context);// Decide for yourself when to switch
if (mq.size.width <= 330 || mq.textScaleFactor >= 1.4) {
    TrainConnectionRowAccessibility();
} else {
    TrainConnectionRowNormal();
}
Auf dem Bild werden zwei inhaltlich identische Bildschirme von SBB Inclusive abgebildet. Es handelt sich dabei um die Standardansicht im Tab «Bahnhof» mit den nächsten Abfahrten. Auf der rechten Seite ist derselbe Bildschirm mit einer starken Vergrösserung abgebildet. Dabei werden die Abfahrten in der Abfahrtstabelle neu angeordnet, damit sie besser lesbar werden. Anstatt dass Zugskategorie und Liniennummer sowie Abfahrtszeit, Ziel, Vias und Abfahrtsgleis horizontal nebeneinanderstehen, werden sie grösstenteils vertikal untereinander angeordnet.
Abbildung 3: Die gleiche Ansicht in regulärer Schriftgrösse (links) und vergrösserter Schriftgrösse (rechts).

Empfehlung 2: Wähle Farben mit Bedacht.

Für Menschen mit einer Sehbehinderung sind gute Kontraste in einer App erfolgsentscheidend. Die Verwendung einer Farbpallette mit wenigen, sorgfältig ausgewählten Farben ist empfehlenswert. Idealerweise enthält diese Palette Vorder- und Hintergrundfarben, welche ein starkes Kontrastverhältnis zueinander aufweisen.

Viele Nutzende mit eingeschränktem Sehvermögen verwenden den Dark Mode, um eine Blendwirkung zu vermeiden. Für die Umsetzung hat das Entwicklungsteam von SBB Inclusive eine Reihe von semantic colors entwickelt. Eine semantic color wird immer für einen bestimmten Zweck verwendet, beispielsweise textBlack für alle normalen Texte in der App. Der semantic color ist dann ein Farbenpaar für den hellen und eines für den dunklen Modus zugeordnet. Dadurch muss die Farbpallette nur einmal definiert werden und wird stets überall in der App gleich verwendet.

SwiftUI

Text(“Bern”)
    .foregroundColor(SBBColor.textBlack)

Flutter

Text(
    ‘Bern’,
    style: Theme.of(context).textTheme.bodyText1
        .copyWith(color: SBBColors.textBlack),
);
Auf dem Bild werden zwei inhaltlich identische Bildschirme von SBB Inclusive abgebildet, einmal in Standardansicht, einmal im Dark Mode. Es handelt sich dabei um die Standardansicht im Tab «Bahnhof» mit den nächsten Abfahrten.
Abbildung 4: Sowohl im hellem (links) als auch im dunklen Modus (rechts) wird durch die Festlegung von semantic colors auf gute Kontraste geachtet.

Empfehlung 3: Optimiere für Screen Reader.

Sich mit Screen Readern vertraut machen

VoiceOver und TalkBack sind weitere wichtige Elemente, die beim Programmieren einer barrierefreien App berücksichtigt werden müssen. Als Entwickler:in lohnt es sich, die Screen Reader selbst regelmässig zu nutzen und als Kurzbefehle auf dem eigenen Gerät einzurichten. Auf diese Weise erhält die Entwickler:in ein Gefühl dafür, was für eine gute Bedienung der App wirklich wichtig ist. Dazu ist es empfehlenswert, auch die Rückmeldungen von Tester:innnen zu berücksichtigen: Sie sind Profis in der Bedienung des Smartphones mit ihrer Behinderung.

Unwichtige visuelle Informationen ausblenden

VoiceOver und TalkBack versuchen, jedes einzelne, visuell vorhandene Element vorzulesen. Dies ist jedoch nicht immer hilfreich. Beispielsweise werden in einer App zur Illustrierung des Textes häufig Symbole oder Bilder verwendet. Für Nutzer:innen mit Screen Readern stellen diese aber eine unnötige Wiederholung dar. Deshalb sind solche Informationen für Screen Reader auszublenden.

SwiftUI

Image(”train-small”)
    .accessibilityHidden(true)

Flutter

Image.asset(
    Images.trainSmall,
    excludeFromSemantics: true,
)

Bessere Texte für Screen Reader bereitstellen

Oft wird die eigentliche Information erst deutlich, wenn ihre einzelnen Teile zusammensetzt werden. Das bedeutet, dass diese Informationen auch für Screen Reader kombiniert werden müssen.

Zeilenweise InformationZusammengefügte Information
“12:39”
“12:40”
“Flawil”
“12:39, 12:40, Flawil, …”
Auch in diesem Bild werden wiederum zwei Bildschirme von SBB Inclusive abgebildet, diesmal wird auch der Screen Reader-Fokus mit einer Umrandung abgebildet. Im linken Bildschirm wird lediglich eine Uhrzeit (Ankunft in Flawil) umrahmt. Im rechten Bildschirm wird der gesamte Eintrag mit den Ankunfts- und Abfahrtszeiten, der Haltestelle, dem Ankunftsgleis und der Ausstiegsseite umrandet. Das bedeutet, dass der Fokus beim rechten Bildschirm auf dem gesamten Textblock liegt, der als Ganzes vorgelesen wird.

SwiftUI

Group {
    Text("12:39")
    Text("12:40")
    …
}.accessibilityElement(children: .combine)

Flutter

MergeSemantics(
    child: Column(
        children: const <Widget>[
            Text('12:39'),
            Text('12:40'),
            …
        ],
    ),
),

Cleveres visuelles Design liefert Kontext zu den dargestellten Informationen, ohne ihn explizit zu nennen. Als Beispiel dient der vorherig abgebildete Bildschirm: Aufgrund der Anordnung ist anzunehmen, dass der Zug um 12:39 Uhr in Flawil ankommt und um 12:40 Uhr abfährt. Diese Informationen werden jedoch nicht ausdrücklich über Texte vermittelt. Für Nutzer:innen mit einem Screen Reader fehlen diese visuellen Abhängigkeiten, weshalb zusätzliche Texte als verbindendes Element hinzugefügt werden müssen.

VorherNachher
“12:39, 12:40, Flawil, …”“Flawil, Ankunft um 12:39, Abfahrt um 12:40, auf Gleis 2, Ausstieg links”

Leider lässt sich dies nicht einfach durch ein simples Attribut im Code erreichen. Deshalb ist es ratsam, einen benutzerdefinierten TextFormatter zu implementieren, der für die Bereitstellung sinnvoller Texte verantwortlich ist.

SwiftUI

Group {
    …
}
    .accessibilityLabel(Text(TextFormatter.stopStation(for: stopStation).voiceover))

Flutter

Semantics(
    value: createSemantics(stopStation),
    child: …,
)

Um schneller zu den gewünschten Inhalten zu springen, ermöglichen Screen Reader die Navigation von Titel zu Titel. Dazu müssen diese im Code entsprechend gekennzeichnet werden.

SwiftUI

Text(”Einstellungen")
    .accessibilityAddTraits(.isHeader)

Flutter

Semantics(
    header: true,
    child: Text('Einstellungen'),
)

Obwohl die Screen Reader sowohl unter iOS als auch unter Android sehr leistungsfähig sind, muss in bestimmten Fällen nachgeholfen werden. Beispielsweise werden Uhrzeiten standardmässig nur sehr schwer verständlich ausgegeben.

SwiftUI

Text(trainConnection.departureTime)
    .accessibilityValue(DateFormatter.hourMinuteVoiceoverTime.string(from: trainConnection.departureTime))

Um die Fälle zu erkennen, in denen VoiceOver und TalkBack nicht perfekt sind, braucht es kontinuierliche Tests durch alle Mitglieder des Entwicklungsteams.

Fazit

Kennt und berücksichtigt man die wichtigsten Prinzipien der digitalen Barrierefreiheit, ist es gar nicht so schwierig, eine App barrierefrei zu gestalten. Es ist wichtig, diese Prinzipien bereits im Design zu berücksichtigen und das Entwicklungsteam entsprechend zu sensibilisieren. So bleibt der zusätzliche Aufwand bei der Programmierung minim. Ausserdem spricht die App dadurch bereits beim Launch ein potenziell grösseres Publikum an, da sie auch von Menschen mit Behinderungen intuitiv verwendet werden kann. Die digitale Barrierefreiheit lädt zu einer spannenden und lehrreichen Reise mit grossem Mehrwert für die Nutzer:innen, aber auch für die Entwicklungsteams ein.

Über die Autoren

Dieser Text wurde erstmalig im August 2020 im Medium-Blog der SBB AppBakery publiziert. Er liegt hier in einer aktualisierten und überarbeiteten Form vor.

Reto Allemann arbeitet als Product Owner von SBB Inclusive. Zusätzlich ist er Innovationsverantwortlicher und begleitet Teams in agilen Arbeitsorganisationen.

Nicolas Brunner war bis 2022 iOS-Entwickler von SBB Inclusive und hat im August 2020 die Basis für diesen Artikel in einem Blogbeitrag auf Medium publiziert.

Jeanne Fleury ist seit 2022 iOS-Entwicklerin bei SBB Inclusive.

Die Entwickler:innen von SBB Inclusive arbeiten bei der AppBakery. Die AppBakery ist eine interne Agentur der SBB, welche mit neuen Technologien innovative Lösungen schafft.