Accessibility Label — это имя элемента интерфейса, которое VoiceOver (iOS) или TalkBack (Android) произносит при фокусе. В iOS свойство называется accessibilityLabel, в Android — contentDescription для элементов, не содержащих текст. По данным Apple Developer Documentation, 2024, метка — основа доступности: без неё пользователь не может идентифицировать элемент. Метка должна быть уникальной в пределах экрана и отражать суть элемента понятным языком.
Главное
Accessibility Label — это строковое свойство, определяющее имя элемента для вспомогательных технологий. Когда пользователь проводит пальцем по экрану с включённым VoiceOver, screen reader зачитывает Label элемента, на котором находится фокус. Без метки пользователь слышит только тип элемента: «кнопка», «изображение» — без указания назначения.
По данным Google I/O 2024, «Accessibility Testing», 35% критических accessibility-нарушений в магазинных приложениях связаны с отсутствием или некорректностью Label. Accessibility Scanner на Android детектирует отсутствие метки как ошибку highest severity.
Принципиальное ограничение: Label не должен содержать тип элемента. VoiceOver и TalkBack автоматически добавляют роль (button, header, link) в объявление. Если Label содержит «Кнопка отправки», пользователь услышит: «Кнопка отправки, кнопка» — дублирование.
WCAG 4.1.2 (уровень A) требует, чтобы каждый элемент пользовательского интерфейса имел программно определяемое имя (name), роль (role) и значение (value). Accessibility Label обеспечивает name. Если Label отсутствует, критерий считается нарушенным, и приложение не проходит базовую сертификацию.
В iOS accessibilityLabel наследуется всеми UIView от протокола UIAccessibility. Если элемент содержит текст (UIButton с title, UILabel с text), Label автоматически устанавливается равным этому тексту. Для UIImageView, кастомных контролов и контейнеров Label нужно задавать вручную.
Пример для кастомной ячейки таблицы:
class CustomTableViewCell: UITableViewCell {
let titleLabel = UILabel()
let priceLabel = UILabel()
override func awakeFromNib() {
super.awakeFromNib()
self.isAccessibilityElement = true
self.accessibilityLabel =
"\(titleLabel.text ?? "") - \(priceLabel.text ?? "")"
}
}
Для кастомных UIView можно переопределить геттер accessibilityLabel:
class RatingView: UIView {
var rating: Int = 5
override var accessibilityLabel: String? {
get { return "Оценка: \(rating) из 5" }
set {}
}
}
Apple HIG, 2024 советует: если элемент состоит из нескольких субэлементов (например, карточка товара с названием и ценой), объедините их в один accessibility-элемент с композитным Label. Установите isAccessibilityElement = true на родителе и false на детях.
Если UILabel использует NSAttributedString, accessibilityLabel по умолчанию равен .string (plain text). Если нужно передать семантически другое значение (например, иконка-символ читается как «Звезда» вместо символа ★), явно установите accessibilityLabel. VoiceOver не читает Unicode-символы осмысленно.
В Android contentDescription выполняет функцию Label для ImageView, ImageButton и кастомных View. Для TextView и Button со встроенным текстом задавать contentDescription не требуется — TalkBack читает текст автоматически.
Программное задание через Kotlin:
binding.iconStar.contentDescription = "Товар в избранном"
// Для кастомной View с множественными элементами
binding.customCard.setContentDescription(
"\(title) на сумму \(price)")
В XML для декоративных элементов:
<ImageView
android:contentDescription="@null"
android:src="@drawable/divider"
android:importantForAccessibility="no" />
Свойство importantForAccessibility = "no" полностью исключает элемент из дерева доступности. В iOS аналог — isAccessibilityElement = false.
В Jetpack Compose Label задаётся через модификатор semantics:
Image(
painter = painterResource(R.drawable.ic_search),
contentDescription = "Поиск товаров",
modifier = Modifier.semantics {
contentDescription = "Поиск товаров"
}
)
В Compose contentDescription — обязательный параметр для Image, без него код не скомпилируется (warning). Это принудительно улучшает accessibility через дизайн API.
Accessibility Label отвечает на вопрос «Что это за элемент?». Hint (accessibilityHint в iOS, дополнительный текст в contentDescription в Android) — «Что произойдёт при взаимодействии?». VoiceOver произносит их последовательно: сначала Label, затем Hint.
Пример для кнопки удаления:
По данным Deque University, 2024, правильное разделение Label и Hint повышает успешность task completion rate для пользователей VoiceOver на 28%. Пользователи с когнитивными нарушениями особенно зависимы от Hint: рискуя нажать «Удалить» без пояснения, 40% отказываются от действия.
Частая ошибка: в Label пишут «Кнопка удаления» вместо «Удалить». Тип элемента (Button) добавляется VoiceOver автоматически через трейт. В результате пользователь слышит: «Кнопка удаления, кнопка» — дублирование. Правильный Label: «Удалить», Hint: «Удалит выбранное фото».
Локализация меток обязательна — она идёт через стандартные механизмы: NSLocalizedString в iOS, строковые ресурсы @string/ в Android. Никогда не задавайте Label конкатенацией на английском без локализации.
Правила хорошего Label, основанные на W3C WCAG 2.2:
Используйте единый глоссарий для Label в приложении. Если на одном экране написано «Избранное», а на другом «Закладки», пользователь дезориентирован. Заведите Accessibility-таблицу терминов — согласуйте с дизайнерами и локализаторами.
Для полей ввода (UITextField, EditText) Label должен совпадать с placeholder или заголовком поля. Однако placeholder часто скрывается после ввода текста. Используйте accessibilityLabel для постоянного имени и accessibilityValue для текущего содержимого поля — это стандарт WCAG 4.1.2. Решение: задайте accessibilityLabel статически (равным заголовку поля), а accessibilityValue — динамически (равным введённому тексту). В iOS это автоматически, но для кастомных полей — вручную через переопределение accessibilityValue. Проверьте, что VoiceOver читает: «Email, example@domain.com, текстовое поле» вместо «, текстовое поле».
Автоматизированное тестирование — единственный способ гарантировать корректность Label на всех экранах. iOS предоставляет XCUIApplication с доступом к .label, Android — AccessibilityCheckRule и setContentDescription.
Пример теста для iOS:
func testLabelsAreUnique() {
let app = XCUIApplication()
app.launch()
let allButtons = app.buttons.allElementsBoundByIndex
let labels = allButtons.compactMap { $0.label }
let uniqueLabels = Set(labels)
XCTAssertEqual(labels.count, uniqueLabels.count,
"Найдены дублирующиеся Label")
}
Пример для Android с Espresso:
@Test
fun testButtonHasAccessibilityLabel() {
onView(withId(R.id.btnSubmit))
.check(matches(
withContentDescription(containsString("Отправить"))
))
}
Ручное тестирование: включите VoiceOver (iOS) или TalkBack (Android) и пройдите жестом вправо по всем элементам экрана. Каждый элемент должен получить осмысленное объявление. Если слышите только «кнопка» или «изображение» — Label отсутствует.
После настройки Label пользователь VoiceOver может использовать ротор для быстрой навигации: режимы «Кнопки», «Заголовки», «Ссылки» и другие. Если Label задан правильно, VoiceOver включает элемент в соответствующий режим ротора. Проверьте, что все кнопки видны в режиме «Кнопки», все заголовки — в «Заголовки».
Label также влияет на поиск VoiceOver. Пользователь может ввести слово в поисковом режиме, и VoiceOver переместит фокус на элемент с подходящим Label. Поэтому в Label должны быть ключевые слова, по которым пользователь будет искать элемент.
Добавьте проверку Label в pipeline. На iOS используйте XCUITest с fastlane scan. На Android — Accessibility Test Framework с правилом AccessibilityCheckRule, которое детектирует пустые contentDescription. Это предотвращает регрессии при мерже новых экранов.
Часто задаваемые вопросы
Label идентифицирует элемент («Поиск»), Hint поясняет результат действия («Откроет экран поиска»). VoiceOver произносит Label сразу при фокусе, а Hint — в режиме подробных описаний.
В iOS UILabel автоматически получает accessibilityLabel, равный своему тексту. Дополнительно задавать не нужно. В Android TextView ведёт себя аналогично.
Установите isAccessibilityElement = true на родительской View и переопределите accessibilityLabel, вернув конкатенированный текст из дочерних элементов. Для сложных компонентов используйте объединение с разделителем.
Добавляйте контекст к повторяющимся элементам: «Купить iPhone 15», «Купить iPhone 15 Pro». Автоматизируйте проверку через UI-тесты — собирайте все Label и проверяйте отсутствие дубликатов.
Нет. Для скрытия элемента используйте isAccessibilityElement = false в iOS или importantForAccessibility = "no" в Android. Пустой Label не скрывает элемент — screen reader прочитает «без названия».
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также