Android View

Přístupný přepínač (Switch) v Android View

Popisek a přepínač vedle sebe jako dva samostatné prvky rozkladu (TextView + Switch) jsou pro TalkBack dvě oddělené zastávky — na přepínač se dostanete zvlášť a uslyšíte jen „přepínač, zapnuto" bez informace, co vlastně přepíná.

1. Špatně — text a přepínač jako dva samostatné View

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="Zvuk při dosažení poslední položky" />

    <com.google.android.material.materialswitch.MaterialSwitch
        android:id="@+id/switchSound"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

2. Správně — text přímo na přepínači

<com.google.android.material.materialswitch.MaterialSwitch
    android:id="@+id/switchSound"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Zvuk při dosažení poslední položky" />

MaterialSwitch (aktuálně doporučená náhrada za starší SwitchMaterial i za čistý Switch/SwitchCompat) je potomek CompoundButton, který svůj android:text vystavuje jako součást přístupného jména automaticky, spolu se stavem. TalkBack přečte „Zvuk při dosažení poslední položky, přepínač, zapnuto" jedním krokem — bez jakékoli ruční práce navíc.

3. Když opravdu potřebujete text a přepínač jako oddělené View

Vestavěný text nejde použít, pokud layout vyžaduje text u levého okraje a přepínač u pravého, roztažené na celou šířku řádku. Nejbližší náhrada je udělat z celého řádku jeden fokusovatelný celek:

<LinearLayout
    android:id="@+id/switchRow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:orientation="horizontal">

    <TextView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:text="Zvuk při dosažení poslední položky" />

    <com.google.android.material.materialswitch.MaterialSwitch
        android:id="@+id/switchSound"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:focusable="false" />
</LinearLayout>

clickable="false"/focusable="false" na obou vnitřních prvcích a clickable="true"/focusable="true" na obalujícím LinearLayout sloučí text potomků do jedné TalkBack zastávky. Tady je ale mezera, kterou se mi nepodařilo dohledat oficiálně zdokumentovanou: sloučení textu je popsané, ale nikde jsem nenašel potvrzení, že se stejně automaticky přenese i stav (zapnuto/vypnuto) a role „přepínač" ze Switch, který teď sám nedostává fokus. V praxi to pravděpodobně vyžaduje doplnit na řádek AccessibilityDelegate, který stav a roli předá ručně:

ViewCompat.setAccessibilityDelegate(switchRow, object : AccessibilityDelegateCompat() {
    override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
        super.onInitializeAccessibilityNodeInfo(host, info)
        info.className = android.widget.Switch::class.java.name
        info.isCheckable = true
        info.isChecked = switchSound.isChecked
    }
})

Tuhle variantu si před nasazením ověřte přímo se zapnutým TalkBackem — na rozdíl od zbytku článku tahle část nemá oporu v žádném oficiálním dokumentu, který bych dohledal.

Proč to takhle je

  • Switch/MaterialSwitch je CompoundButton a nativně vystavuje svůj android:text jako součást přístupného jména společně se stavem — proto první, jednodušší řešení nepotřebuje nic navíc.
  • Sloučení přes clickable/focusable je oficiálně zdokumentované pro text potomků, ne prokazatelně pro stav a roli — to je rozdíl oproti přístupům, kde jeden modifier/atribut řeší obojí najednou.
  • MaterialSwitch je aktuálně doporučená volba — lint upozorňuje na použití staršího čistého Switch v XML.

Pravidla

  • WCAG 4.1.2 (Název, role, hodnota) — přepínač musí programově hlásit svou roli, stav i název jako jeden celek, ne jako tři nesouvisející kusy informace.

Zdroje

Štítky

Komentáře

Zatím zde nejsou žádné komentáře. Buďte první, kdo napíše svůj názor.

Přidat komentář k „Přístupný přepínač (Switch) v Android View“