Accessibility Label е името на интерфейсния елемент, което VoiceOver (iOS) или TalkBack (Android) изговаря при фокусиране. В iOS свойството се нарича accessibilityLabel, в Android — contentDescription за елементи, които не съдържат текст. Според Apple Developer Documentation, 2024етикетът е основата на достъпността: без него потребителят не може да идентифицира елемента. Етикетът трябва да бъде уникален в рамките на екрана и да отразява същността на елемента на разбираем език.
Основни моменти
Accessibility Label е текстово свойство, което определя името на елемента за помагащите технологии. Когато потребителят прекарва пръст по екрана с включен VoiceOver, екранният четец изговаря Label на елемента, на който е фокусът. Без етикет потребителят чува само типа на елемента: „бутон”, „изображение” — без посочване на предназначението.
Според Google I/O 2024, „Accessibility Testing” 35% от критичните нарушения на достъпността в магазинените приложения са свързани с липса или некоректност на Label. Accessibility Scanner на Android открива липсата на етикет като грешка от най-висока тежест.
Принципно ограничение: Label не трябва да съдържа типа на елемента. VoiceOver и TalkBack автоматично добавят ролята (button, header, link) в съобщението. Ако Label съдържа „Бутон за изпращане”, потребителят ще чуе: „Бутон за изпращане, бутон” — дублиране.
WCAG 4.1.2 (ниво A) изисква всеки елемент на потребителския интерфейс да има име (name), роля (role) и стойност (value), които могат да бъдат определени програмно. Accessibility Label осигурява името. Ако 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 препоръчва: ако елементът се състои от няколко поделемента (напр. картичка на продукт с име и цена), комбинирайте ги в един елемент за достъпност с композитен Label. Настройте isAccessibilityElement = true на родителя и false на децата.
Ако UILabel използва NSAttributedString, accessibilityLabel по подразбиране е равен на .string (обикновен текст). Ако трябва да предадете семантично различна стойност (напр. икона-символ, която се чете като „Звезда” вместо символа ★), изрично настройте 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 — без него кодът няма да се компилира (предупреждение). Това принудително подобрява достъпността чрез дизайна на API.
Accessibility Label отговаря на въпроса „Какъв е този елемент?”. Hint (accessibilityHint в iOS, допълнителен текст в contentDescription в Android) — „Какво ще се случи при взаимодействие?”. VoiceOver ги изговаря последователно: първо Label, след това Hint.
Пример за бутон за изтриване:
Според Deque University, 2024 правилното разделяне на Label и Hint повишава процента на успешно изпълнение на задачите за потребителите на VoiceOver с 28%. Потребителите с когнитивни нарушения са особено зависими от Hint: рискувайки да натиснат „Изтрий” без обяснение, 40% се отказват от действието.
Честа грешка: в Label пишат „Бутон за изтриване” вместо „Изтрий”. Типът на елемента (бутон) се добавя автоматично от VoiceOver чрез trait. В резултат потребителят чува: „Бутон за изтриване, бутон” — дублиране. Правилен Label: „Изтрий”, Hint: „Ще изтрие избраната снимка”.
Локализацията на етикетите е задължителна — става чрез стандартни механизми: NSLocalizedString в iOS, ресурси за низки @string/ в Android. Никога не настройвайте Label чрез конкатенация на английски без локализация.
Правила за добър Label, основани на W3C WCAG 2.2:
Използвайте единен речник за Label в приложението. Ако на един екран е написано „Любими”, а на друг „Отметки”, потребителят е дезориентиран. Създайте таблица на термините за достъпност — съгласувайте с дизайнерите и локализаторите.
За полета за ввеждане (UITextField, EditText) Label трябва да съвпада с placeholder или заглавието на полето. Плейсхолдърът обаче често изчезва след ввеждане на текст. Използвайте accessibilityLabel за постоянното име и accessibilityValue за текущото съдържание на полето — това е стандартът WCAG 4.1.2. Решение: настройте accessibilityLabel статично (равно на заглавието на полето), а accessibilityValue динамично (равно на въведения текст). В iOS това е автоматично, но за поръчени полета — ръчно чрез предефиниране на accessibilityValue. Проверете дали VoiceOver чете: „Имейл, 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 в пайплайна. На 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 не скрива елемента — екранният четец ще прочете „без име”.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също