Jak označit text jako nadpis (Jetpack Compose)
TalkBack umí přeskakovat po nadpisech stejně jako čtečky obrazovky na webu po <h1>–<h6> — jenže v Jetpack Compose žádné <h1> neexistuje. Vizuálně velké a tučné písmo z MaterialTheme.typography.headlineX je jen styl, ne sémantika — TalkBack ho jako nadpis nepřečte, dokud mu to neřeknete výslovně.
1. Jak na to
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
Text(
text = "Nadpis sekce",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.semantics { heading() }
)
heading() je funkce, kterou zavoláte uvnitř semantics { } bloku na modifieru daného Text (nebo jiného composable). Nastaví v sémantickém stromu příznak, díky kterému TalkBack prvek rozpozná a zpřístupní ho navigaci po nadpisech (gesto pro změnu granularity čtení → „Nadpisy" → přeskakování mezi nimi).
2. Co to dělá a co ne
heading()je čistě binární příznak — buď prvek nadpisem je, nebo není. Na rozdíl od HTML tu neexistuje úroveň nadpisu (žádná obdoba h1 vs. h2 vs. h3). Vizuální hierarchii (headlineLargevs.headlineSmallvs.titleMedium...) sice pořád můžete a měli byste používat pro vzhled, ale TalkBack z ní žádnou úroveň nevyčte — všechny označené nadpisy jsou si z pohledu navigace rovny.- Neexistuje ani
Role.Heading— možná byste čekali, že nadpis půjde nastavit stejně jakoRole.ButtonneboRole.Checkboxpřesrole = ..., ale sada rolí v Compose nadpis vůbec neobsahuje.Headingje samostatný sémantický klíč, ne role.
3. Nejčastější chyba
Použít jen velký/tučný styl a myslet si, že tím je nadpis hotový:
// TOHLE NESTAČÍ — je to jen vizuál, TalkBack o tom neví
Text(
text = "Nadpis sekce",
style = MaterialTheme.typography.headlineMedium
)
Přesně stejná past jako na webu, kde velké tučné písmo taky není nadpis, dokud nejde o skutečný <h1>–<h6> prvek (nebo role="heading" s aria-level). Vzhled a sémantika jsou tu dvě oddělené věci, které je potřeba nastavit obě.
4. Jak si to ověřit
- Layout Inspector v Android Studiu — vyberte si composable a v panelu Attributes uvidíte, jestli mezi jeho sémantickými vlastnostmi je
Heading. - Ručně s TalkBackem — zapněte TalkBack, přepněte granularitu čtení na „Nadpisy" a projeďte gestem obrazovku; správně označený prvek se objeví v tomhle přeskakování.
- Accessibility Test Framework (součást Compose testů od verze 1.8.0, balíček
ui-test-junit4-accessibility) — automatizované kontroly přímo v testech:composeTestRule.enableAccessibilityChecks() composeTestRule.onRoot().tryPerformAccessibilityChecks()Nekontroluje přímo „je tohle nadpis", ale odchytí širší okruh problémů (kontrast, velikost dotykové plochy, chybějící popisky) v rámci běžného testovacího běhu.
Proč to takhle je
- Compose odděluje vzhled (
TextStyle) od sémantiky (Modifier.semantics) úplně stejně, jako to dělá HTML/ARIA na webu — vizuální styl nikdy sám o sobě nic neříká asistivní technologii, musí se to napsat výslovně. - Chybějící úroveň nadpisu je vědomé zjednodušení Compose sémantiky oproti HTML — u složitější stránky/obrazovky s víceúrovňovou hierarchií to znamená, že se spolehnout jen na navigaci „po nadpisech" nemusí stačit k pochopení struktury tak dobře, jako to jde na webu.
Pravidla
- Analogie WCAG 2.4.6 (Nadpisy a popisky) a 1.3.1 (Info a vztahy) — i když se WCAG formálně vztahuje na web, princip (struktura obsahu musí být zjistitelná programově, ne jen vizuálně) je stejný a Google se jím v Android accessibility guidelines výslovně řídí.
- Google Android accessibility: text musí nést svůj význam i mimo vizuální prezentaci — přesně tohle
heading()řeší.
Komentáře
Zatím zde nejsou žádné komentáře. Buďte první, kdo napíše svůj názor.
Přidat komentář k „Jak označit text jako nadpis (Jetpack Compose)“