Accessibility Label je název prvku rozhraní, který VoiceOver (iOS) nebo TalkBack (Android) vysloví při zaostření. V iOS se vlastnost nazývá accessibilityLabel, v Androidu — contentDescription pro prvky, které neobsahují text. Podle Apple Developer Documentation, 2024 je štítek základem přístupnosti: bez něj uživatel nemůže prvek identifikovat. Štítek musí být v rámci obrazovky jedinečný a odrážet podstatu prvku srozumitelným jazykem.
Hlavní body
Accessibility Label je řetězcová vlastnost, která definuje název prvku pro asistenční technologie. Když uživatel přejížčí prstem po obrazovce s zapnutým VoiceOver, čtečka obrazovky přečte Label prvku, na kterém je zaostřeno. Bez štítku uživatel slyší pouze typ prvku: „tlačítko”, „obrázek” — bez uvedení účelu.
Podle Google I/O 2024, „Accessibility Testing” souvisí 35% kritických porušení přístupnosti v obchodních aplikacích s chybějícím nebo nesprávným Label. Accessibility Scanner na Androidu detekuje chybějící štítek jako chybu nejvyšší závažnosti.
Základní omezení: Label nesmí obsahovat typ prvku. VoiceOver a TalkBack automaticky přidávají roli (button, header, link) do oznámení. Pokud Label obsahuje „Tlačítko odeslání”, uživatel uslyší: „Tlačítko odeslání, tlačítko” — duplicita.
WCAG 4.1.2 (úroveň A) vyžaduje, aby každý prvek uživatelského rozhraní měl programově zjistitelné jméno (name), roli (role) a hodnotu (value). Accessibility Label poskytuje jméno. Pokud Label chybí, je kritérium považováno za porušené a aplikace neprojde základní certifikací.
V iOS je accessibilityLabel děděna všemi UIView z protokolu UIAccessibility. Pokud prvek obsahuje text (UIButton s title, UILabel s text), Label se automaticky nastaví na tento text. Pro UIImageView, vlastní ovládací prvky a kontejnery je třeba Label nastavit ručně.
Příklad pro vlastní buňku tabulky:
class CustomTableViewCell: UITableViewCell {
let titleLabel = UILabel()
let priceLabel = UILabel()
override func awakeFromNib() {
super.awakeFromNib()
self.isAccessibilityElement = true
self.accessibilityLabel =
"\(titleLabel.text ?? "") - \(priceLabel.text ?? "")"
}
}
Pro vlastní UIView lze přepsat getter accessibilityLabel:
class RatingView: UIView {
var rating: Int = 5
override var accessibilityLabel: String? {
get { return "Hodnocení: \(rating) z 5" }
set {}
}
}
Apple HIG, 2024 doporučuje: pokud se prvek skládá z několika podprvků (např. karta produktu s názvem a cenou), spojte je do jednoho prvku přístupnosti s kompozitním Labilem. Nastavte isAccessibilityElement = true na rodiči a false na dětech.
Pokud UILabel používá NSAttributedString, accessibilityLabel je implicitně roven .string (prostý text). Pokud potřebujete předat sémanticky jinou hodnotu (např. ikona-symbol čtená jako „ hvězda” místo symbolu ★), explicitně nastavte accessibilityLabel. VoiceOver nečte Unicode symboly smysluplně.
V Androidu plní contentDescription funkci Label pro ImageView, ImageButton a vlastní View. Pro TextView a Button s vestavěným textem není třeba contentDescription nastavovat — TalkBack čte text automaticky.
Programové nastavení pomocí Kotlin:
binding.iconStar.contentDescription = "Produkt v oblíbených"
// Pro vlastní zobrazení s více prvky
binding.customCard.setContentDescription(
"\(title) v částce \(price)")
V XML pro dekorativní prvky:
<ImageView
android:contentDescription="@null"
android:src="@drawable/divider"
android:importantForAccessibility="no" />
Vlastnost importantForAccessibility = "no" zcela vylučuje prvek ze stromu přístupnosti. V iOS je analogií isAccessibilityElement = false.
V Jetpack Compose se Label nastavuje pomocí modifikátoru semantics:
Image(
painter = painterResource(R.drawable.ic_search),
contentDescription = "Vyhledávání produktů",
modifier = Modifier.semantics {
contentDescription = "Vyhledávání produktů"
}
)
V Compose je contentDescription povinným parametrem pro Image — bez něj se kód nezkompiluje (varování). To vynucuje zlepšení přístupnosti prostřednictvím návrhu API.
Accessibility Label odpovídá na otázku „Co je to za prvek?”. Hint (accessibilityHint v iOS, doplňující text v contentDescription v Androidu) — „Co se stane při interakci?”. VoiceOver je vyslovuje postupně: nejprve Label, poté Hint.
Příklad pro tlačítko smazání:
Podle Deque University, 2024 správné oddělení Label a Hint zvyšuje míru úspěšného dokončení úkolů pro uživatele VoiceOver o 28%. Uživatelé s kognitivním postižením jsou zvláště závislí na Hint: s rizikem stisknutí „Smazat” bez vysvětlení 40% od akce upouští.
Častá chyba: v Label píší „Tlačítko smazání” místo „Smazat”. Typ prvku (tlačítko) je automaticky přidán VoiceOver prostřednictvím trait. Výsledkem je, že uživatel slyší: „Tlačítko smazání, tlačítko” — duplicita. Správný Label: „Smazat”, Hint: „Smaže vybranou fotografii”.
Lokalizace štítků je povinná — probíhá prostřednictvím standardních mechanismů: NSLocalizedString v iOS, zdroje řetězců @string/ v Androidu. Nikdy nenastavujte Label konkatenací v angličtině bez lokalizace.
Pravidla dobrého Label, založená na W3C WCAG 2.2:
Používejte jednotný slovník pro Label v aplikaci. Pokud je na jedné obrazovce napsáno „Oblíbené” a na druhé „Záložky”, uživatel je dezorientován. Vytvořte tabulku termínů přístupnosti — dohodněte se s designéry a lokalizátory.
Pro vstupní pole (UITextField, EditText) by se Label měl shodovat s placeholderem nebo názvem pole. Placeholder však po zadání textu často zmizí. Použijte accessibilityLabel pro trvalý název a accessibilityValue pro aktuální obsah pole — to je standard WCAG 4.1.2. Řešení: nastavte accessibilityLabel staticky (rovný názvu pole) a accessibilityValue dynamicky (rovný zadanému textu). V iOS je to automatické, ale pro vlastní pole — ručně přepsáním accessibilityValue. Zkontrolujte, že VoiceOver čte: „Email, example@domain.com, textové pole” místo „, textové pole”.
Automatizované testování je jediný způsob, jak zaručit správnost Label na všech obrazovkách. iOS poskytuje XCUIApplication s přístupem k .label, Android — AccessibilityCheckRule a setContentDescription.
Příklad testu pro 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,
"Nalezeny duplicitní Label")
}
Příklad pro Android s Espresso:
@Test
fun testButtonHasAccessibilityLabel() {
onView(withId(R.id.btnSubmit))
.check(matches(
withContentDescription(containsString("Odeslat"))
))
}
Ruční testování: zapněte VoiceOver (iOS) nebo TalkBack (Android) a přejeďte gestem doprava přes všechny prvky obrazovky. Každý prvek by měl obdržet smysluplné oznámení. Pokud slyšíte pouze „tlačítko” nebo „obrázek” — Label chybí.
Po nastavení Label může uživatel VoiceOver použít rotor pro rychlou navigaci: režimy „Tlačítka”, „Nadpisy”, „Odkazy” a další. Pokud je Label správně nastaven, VoiceOver zahrne prvek do příslušného režimu rotoru. Zkontrolujte, že všechna tlačítka jsou viditelná v režimu „Tlačítka” a všechny nadpisy v „Nadpisy”.
Label ovlivňuje také vyhledávání VoiceOver. Uživatel může zadat slovo v režimu vyhledávání a VoiceOver přesune zaměření na prvek s odpovídajícím Labelem. Proto by Label měl obsahovat klíčová slova, podle kterých bude uživatel prvek hledat.
Přidejte kontrolu Label do pipeline. Na iOS použijte XCUITest s fastlane scan. Na Android — Accessibility Test Framework s pravidlem AccessibilityCheckRule, které detekuje prázdné contentDescription. To zabraňuje regresím při slučování nových obrazovek.
Často kladené otázky
Label identifikuje prvek („Vyhledávání”), Hint vysvětluje výsledek akce („Otevře obrazovku vyhledávání”). VoiceOver vysloví Label ihned při zaostření a Hint v režimu podrobných popisů.
V iOS UILabel automaticky získá accessibilityLabel rovný svému textu. Další nastavení není nutné. V Androidu se TextView chová obdobně.
Nastavte isAccessibilityElement = true na nadřazeném View a přepište accessibilityLabel, který vrátí zřetězený text z dceřiných prvků. Pro složité komponenty použijte spojení s oddělovačem.
Přidejte kontext opakujícím se prvkům: „Koupit iPhone 15”, „Koupit iPhone 15 Pro”. Automatizujte kontrolu pomocí UI testů — shromážděte všechny Label a zkontrolujte absenci duplicit.
Ne. Pro skrytí prvku použijte isAccessibilityElement = false v iOS nebo importantForAccessibility = "no" v Androidu. Prázdný Label prvek neskrývá — čtečka obrazovky přečte „bez názvu”.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také