Доступність мобільних застосунків: VoiceOver, TalkBack та WCAG на практиці
Нам не раз доводилося бачити, як застосунок відхиляють в App Store через гайдлайн 1.1 або корпоративний клієнт вимагає WCAG 2.1 AA. Accessibility не закладений в архітектуру з самого початку — вбудовувати його в готовий продукт боляче. Ми знаємо, як це виправити, і маємо досвід 5+ років у цій сфері.
Чому не варто відкладати доступність?
Чому «додати доступність потім» не працює
Найчастіша проблема — розробники сприймають VoiceOver і TalkBack як косметику. Розставили accessibilityLabel, запустили Screen Reader і здивувалися, чому фокус стрибає з кнопки «Купити» на декоративну іконку в кутку.
На iOS помилка живе в неправильному групуванні елементів. Якщо UIStackView містить іконку + текст + ціну, VoiceOver читатиме їх як три окремих елементи замість одного. Рішення — isAccessibilityElement = false на контейнері + accessibilityElements з потрібним порядком, або shouldGroupAccessibilityChildren = true. Здається дрібницею, але саме це робить різницю між «формально працює» та «сліпий користувач може купити товар за 30 секунд».
На Android ситуація дзеркальна: contentDescription ставлять скрізь, включаючи ImageView, які несуть лише декоративну функцію. TalkBack починає зачитувати «іконка стрілка» між кожним значущим елементом. Правильно — android:importantForAccessibility="no" для декору та явні contentDescription лише там, де це несе сенс.
Правильне налаштування скорочує час тестування втричі порівняно з постфактум-виправленнями. Ми гарантуємо відповідність WCAG 2.1 AA у вашому проекті.
Dynamic Type та масштабування шрифтів
iOS Dynamic Type ламає верстку передбачувано: фіксовані висоти рядків у UILabel, захардкоджені frame в Auto Layout, numberOfLines = 1 без adjustsFontSizeToFitWidth. Коли користувач ставить розмір шрифту XXL в налаштуваннях, текст обрізається або перекриває сусідні елементи.
Правильна реалізація використовує .font = UIFont.preferredFont(forTextStyle: .body) з adjustsFontForContentSizeCategory = true та numberOfLines = 0 скрізь, де контент динамічний. У SwiftUI це працює з коробки через .dynamicTypeSize() modifier.
На стороні Flutter еквівалент — textScaleFactor через MediaQuery. Компоненти Material 3 підтримують масштабування нативно, але кастомні віджети вимагають явного врахування.
WCAG 2.1 в мобільному контексті
Мобільні застосунки формально не зобов’язані слідувати WCAG (він писався для вебу), але WCAG 2.1 + доповнення WCAG для мобільних стали де-факто стандартом при корпоративних тендерах та держзакупівлях.
Які критерії WCAG найважливіші для мобільних застосунків?
Критичні критерії стосовно мобілки:
- 1.4.3 Contrast Minimum — співвідношення контрасту тексту до фону мінімум 4.5:1. Перевіряємо через Xcode Accessibility Inspector або Android Studio Layout Inspector
- 2.4.7 Focus Visible — при роботі з зовнішньою клавіатурою на iPad/Android планшеті фокус повинен бути видимий. Часто забутий сценарій
- 2.5.8 Target Size (AA) — мінімум 24x24dp для інтерактивних елементів, рекомендується 44pt/48dp
-
4.1.3 Status Messages — повідомлення про помилки форм повинні озвучуватися через
UIAccessibility.post(notification: .announcement)абоAccessibilityNodeInfo.RoleDescriptionна Android
Порівняння підходів iOS та Android до критичних помилок
| Типова помилка | iOS (Swift) | Android (Kotlin) |
|---|---|---|
| Неправильне групування | shouldGroupAccessibilityChildren |
importantForAccessibility, accessibilityTraversalAfter |
| Відсутній фокус | canBecomeFocused для елементів |
focusable="true" + nextFocusForward |
| Масштабування тексту | UIFont.preferredFont + Dynamic Type |
systemFontSize, autoSizeStepGranularity |
| Озвучення статусу | UIAccessibility.post(notification:announcement) |
announceForAccessibility() / sendAccessibilityEvent() |
Як будуємо процес
Ми починаємо з аудиту: Accessibility Inspector в Xcode та TalkBack developer settings на Android — проходимо всі екрани з увімкненим Screen Reader і фіксуємо кожен випадок, коли потрібно більше 3 дій для виконання цільової операції. Далі — автоматизовані перевірки: XCUITest підтримує accessibility assertions; для Android використовуємо Accessibility Test Framework (ATF), вбудований в Espresso. Це ловить регресії на CI. Фінальний етап — тестування з реальними користувачами, які використовують допоміжні технології. Жодною автоматизацією це не замінити.
| Інструмент | Платформа | Що перевіряє |
|---|---|---|
| Xcode Accessibility Inspector | iOS/macOS | Мітки, контраст, порядок фокусу |
| Android Accessibility Scanner | Android | Контраст, розміри touch targets |
| Deque axe DevTools | Cross-platform | WCAG-відповідність |
| VoiceOver (iOS) | iOS | Навігація через Screen Reader |
| TalkBack (Android) | Android | Навігація через Screen Reader |
Що входить у роботу
Пропонуємо варіант «під ключ»: від аудиту до передачі документації. У результаті ви отримуєте:
- Детальний звіт зі знайденими порушеннями та пріоритетами виправлень.
- Виправлений код з коментарями (Swift, Kotlin, Flutter або React Native).
- Документацію для команди щодо підтримки accessibility далі.
- Навчання розробників (2–4 години воркшопу).
- Гарантію на виправлення — 6 місяців безкоштовної підтримки регресій.
Ми впровадили accessibility у 20+ застосунках різного масштабу — від фінансових додатків до медичних систем. Оцінимо ваш проект безкоштовно. Зв'яжіться з нами, щоб отримати консультацію та приклад звіту з реального кейсу.







