Доступность мобильных приложений: поддержка VoiceOver и TalkBack
Практика3 минРедакция Innovialabs
Коротко
Приложение доступно, когда каждый интерактивный элемент имеет понятную подпись и роль, фокус идёт в логичном порядке, текст масштабируется, контраст достаточен, а зоны касания крупные. Проверять это нужно с включёнными VoiceOver и TalkBack на реальном телефоне.
Коротко: что значит «доступное приложение»
VoiceOver (iOS) и TalkBack (Android) — встроенные скринридеры. Они озвучивают элемент под фокусом, а пользователь перемещается свайпами и активирует элементы двойным касанием. Если у кнопки нет подписи, человек услышит «кнопка» и не поймёт, что она делает.
Минимальный набор требований:
- у каждого интерактивного элемента есть подпись и роль;
- порядок фокуса совпадает с логикой экрана;
- текст поддерживает динамический размер шрифта;
- достаточный контраст;
- зоны касания не меньше рекомендуемых платформой.
Это полезно не только незрячим: крупный шрифт включают люди со слабым зрением, а контраст важен всем на ярком солнце.
Подписи и роли
Подпись (label) описывает, что это, коротко и без слова «кнопка» — роль скринридер добавит сам.
| Платформа | Подпись | Роль / заголовок |
|---|---|---|
| SwiftUI | .accessibilityLabel("Удалить") | .accessibilityAddTraits(.isHeader) |
| UIKit | accessibilityLabel | accessibilityTraits |
| Jetpack Compose | contentDescription / semantics | Modifier.semantics { heading() } |
| Android View | android:contentDescription | accessibilityHeading |
| React Native | accessibilityLabel | accessibilityRole |
Правила:
- Иконка-кнопка без текста — обязательно с подписью: «Поиск», а не «лупа».
- Декоративные изображения скрывайте от скринридера, чтобы не создавать шум.
- Состояние передавайте явно: «Избранное, выбрано» вместо смены цвета сердечка.
- Подсказка (hint) — для неочевидных действий, а не для каждого элемента.
Button(action: deleteItem) {
Image(systemName: "trash")
}
.accessibilityLabel("Удалить заказ")
Порядок фокуса и группировка
Скринридер обходит элементы примерно в порядке слева направо, сверху вниз. Проблемы начинаются с нестандартной вёрстки: абсолютное позиционирование, наложения, карточки из многих мелких элементов.
- Группируйте связанные элементы. Карточка товара должна читаться одним фокусом — название, цена и наличие подряд, — а не тремя отдельными остановками. В SwiftUI —
.accessibilityElement(children: .combine), в Compose —Modifier.semantics(mergeDescendants = true). - При открытии модального окна фокус должен переходить в него, а при закрытии — возвращаться к элементу, который его вызвал.
- Отмечайте заголовки — пользователи скринридеров перемещаются по ним, как по оглавлению.
Динамический шрифт и контраст
- iOS: используйте текстовые стили (
.body,.headline) или масштабируемые шрифты — тогда текст реагирует на системную настройку размера. - Android: задавайте размер текста в sp, а не в dp.
- Проверяйте экраны на самом крупном размере: текст должен переноситься, а не обрезаться, а контейнеры — расти по высоте.
- Контраст обычного текста — не ниже 4.5:1, крупного — 3:1 по WCAG. Цвет не должен быть единственным носителем смысла: ошибку поля подкрепите текстом.
Размер зон касания
- Apple HIG: не меньше 44×44 pt.
- Material Design: не меньше 48×48 dp.
Иконка может быть маленькой визуально, но область касания — расширена отступами. Между соседними целями оставляйте промежуток, чтобы не промахиваться.
Как тестировать на реальных устройствах
- Включите VoiceOver (Настройки → Универсальный доступ) или TalkBack (Настройки → Специальные возможности). Назначьте быстрое включение — например, тройное нажатие боковой кнопки на iPhone.
- Пройдите ключевые сценарии только свайпами, не глядя на экран: регистрация, поиск, оплата.
- Проверьте, что каждая подпись понятна без визуального контекста.
- Включите максимальный размер шрифта и пройдите те же экраны.
- Используйте инструменты: Accessibility Inspector в Xcode и Accessibility Scanner на Android. Они находят отсутствующие подписи, мелкие цели и слабый контраст, но не заменяют ручную проверку.