Elemento focalizzabile annidato

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard
Not for use with personal data

La norma WCAG 2.0 - 4.1.2 A Impatto - Critico

Gli elementi focalizzabili non dovrebbero essere annidati all'interno di elementi genitori cliccabili, perché non annunceranno correttamente il loro ruolo alle tecnologie assistive come TalkBack e Voice Access.

Su questa regola

La regola sull'elemento focalizzabile annidato controlla tutti i controlli di accessibilità focalizzabili annidati che non sono interattivi. Se un tale controllo è contenuto all'interno di un elemento padre cliccabile, è intrinsecamente interattivo, ma non annuncerà un ruolo. Pertanto, questo elemento verrà segnalato come violazione dell'accessibilità.

Impatto sugli utenti

Quando le tecnologie assistive non annunciano un ruolo, gli utenti non vedenti o ipovedenti che si affidano a tecnologie assistive come TalkBack non sapranno di poter attivare un'azione. Ad esempio, TalkBack si concentra su un elemento interno e annuncia solo il testo «Launch a Toast», e nient'altro. Non annuncia che si tratta di un pulsante o che l'utente deve toccare due volte l'elemento per attivarlo.

Conferma

  1. Attivi TalkBack / lettore dello schermo.
  2. Focalizzi la vista e ciascuno dei suoi discendenti.
  3. Si verificherà una delle seguenti situazioni:
    • Inaccessibile: TalkBack legge il testo ma non annuncia un ruolo o la possibilità di interagire.
    • Accessibile: TalkBack legge tutto il testo. Annuncia anche un ruolo e/o indica come interagire con l'elemento.

Come risolvere

Non annidare un controllo focalizzabile e non interattivo all'interno di un elemento padre cliccabile. Si assicuri che il controllo annidato non abbia alcuna proprietà impostata che lo renda focalizzabile. In questo modo l'elemento padre interattivo può ottenere il focus e annunciare il suo ruolo. Veda esempi specifici di seguito.

tip

Per evitare un falso positivo di accessibilità, assicuri che le view di contenitore che non fanno nulla quando vengono toccate non siano impostate come cliccabili. I nostri strumenti non possono determinare se una vista cliccabile abbia un'azione programmata associata, quindi dobbiamo presumere che ne abbia una per segnalare un comportamento potenzialmente non accessibile.

Esamini i container circostanti, come Frame Layout, Card View o Drawer, per assicurarsi che qualsiasi vista a cui non dovrebbe essere associata un'azione non sia impostata come cliccabile.

XML

Esempio non conforme

In questo esempio, MaterialCardView è cliccabile, ma il suo elemento figlio LinearLayout riceve invece il focus. Quando gli utenti delle tecnologie assistive interagiscono con il LinearLayout, viene attivata l'azione di clic sulla scheda, ma non viene annunciato che è cliccabile. Questo comporta un'esperienza non accessibile con la tecnologia assistiva, perché né il ruolo dell'elemento né la descrizione del ruolo indicano che è presente un'azione o quale sarà il risultato dell'interazione.

Avvii una scheda Toast con il contorno di messa a fuoco all'interno
<com.google.android.material.card.MaterialCardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:layout_margin="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/launch_a_toast"/>

    </LinearLayout>

</com.google.android.material.card.MaterialCardView>

Guida alla correzione: imposta LinearLayout:focusable su falso

Assicurarsi che LinearLayout non abbia la proprietà focusable impostata su true. Per impostazione predefinita è falso.

Avvii una scheda Toast con il contorno di messa a fuoco all'esterno
<com.google.android.material.card.MaterialCardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/launch_a_toast"/>

    </LinearLayout>

</com.google.android.material.card.MaterialCardView>

Comporre

Esempio non conforme

In questo esempio, la Card è cliccabile, ma invece riceve il focus l'elemento figlio Row. Quando gli utenti delle tecnologie assistive interagiscono con la Row, questo attiva l'azione di click sulla scheda, ma non viene annunciato che è cliccabile. Questo comporta un'esperienza non accessibile con la tecnologia assistiva, perché né il ruolo dell'elemento né la descrizione del ruolo indicano che è presente un'azione o quale sarà il risultato dell'interazione.

Avvia una scheda Toast con il bordo di messa a fuoco all'esterno
Card(
    modifier = Modifier
        .clickable {
            launchToast(context)
        }
) {
    Row(
        modifier = Modifier
            .focusable()
            .padding(10.dp),
        horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally)
    ) {
        Text(stringResource(R.string.launch_a_toast))
    }
}

Guida alla correzione: Rimuovere la possibilità di ricevere il focus dall'elemento discendente

Qui la possibilità di ricevere il focus è stata rimossa dall'elemento Row. Il Card ora avrà del testo da pronunciare, perché riceverà informazioni dal Text. Il Card ora potrà ricevere il focus tramite tecnologia assistiva e annuncerà il contenuto testuale. La scheda comunicherà all'utente che è cliccabile tramite una descrizione del ruolo come "Tocca due volte per attivare", garantendo così un'esperienza accessibile per l'utente.

Avvia una scheda Toast con il contorno di messa a fuoco all'esterno
Card(
    modifier = Modifier
        .clickable {
            launchToast(context)
        }
) {
    Row(
        modifier = Modifier
            .padding(10.dp),
        horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally)
    ) {
        Text(stringResource(R.string.launch_a_toast))
    }
}

.NET MAUI

Esempio non conforme

In questo esempio, il layout è cliccabile; tuttavia, è stato nascosto nell'albero di accessibilità. Rimuovendo questa view, abbiamo eliminato il contesto che indicava che questa view funzionava come un pulsante, e gli utenti delle tecnologie assistive non sapranno come interagire con essa.

Riquadro con la scritta 'Testo con antenato cliccabile accessibile' contornato in rosso per mostrare che non risulta nell'albero di accessibilità.
<Grid
        HorizontalOptions="FillAndExpand"
        RowDefinitions="Auto,Auto"
        RowSpacing="10"
        VerticalOptions="FillAndExpand"
        AutomationProperties.IsInAccessibleTree="false">

        <Grid.GestureRecognizers>
            <TapGestureRecognizer Command="{Binding Function}"/>
        </Grid.GestureRecognizers>

        <Label
            Grid.Row="1"
            FontAttributes="Bold"
            FontSize="16"
            HorizontalOptions="CenterAndExpand"
            VerticalOptions="FillAndExpand">
            <Label.FormattedText>
                <FormattedString>
                    <Span Text="Text with a clickable parent"/>
                </FormattedString>
            </Label.FormattedText>
        </Label>
    </Grid>

Guida alla correzione: usa la proprietà SemanticProperties.Hint

Gli errori di accessibilità possono essere affrontati in due modi. Il modo più semplice è rimuovere l'elemento AutomationProperties.IsInAccessibleTree="false" dalla vista griglia. Se ciò dovesse entrare in conflitto con altre funzionalità dell'app, un altro modo per fornire agli utenti le azioni di clic è impostare la proprietà SemanticProperties.Hint con informazioni utili sul tipo di elemento con cui l'utente sta interagendo, come "Pulsante" o "Interruttore". Questo permetterà alla tecnologia assistiva di aggiungere correttamente il suggerimento "Doppio tocco per attivare" alla sua lettura e di fornire agli utenti il feedback necessario per interagire con la vista.

Scheda con la scritta 'Testo con un antenato cliccabile che è accessibile', contornata di verde per indicare che si trova nell'albero di accessibilità
<Grid
    HorizontalOptions="FillAndExpand"
    RowDefinitions="Auto,Auto"
    RowSpacing="10"
    VerticalOptions="FillAndExpand">

    <Grid.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding Function}"/>
    </Grid.GestureRecognizers>

    <Label
        Grid.Row="1"
        FontAttributes="Bold"
        FontSize="16"
        HorizontalOptions="CenterAndExpand"
        VerticalOptions="FillAndExpand">
        <Label.FormattedText>
            <FormattedString>
                <Span Text="Text with a clickable parent"/>
            </FormattedString>
        </Label.FormattedText>
    </Label>
</Grid>

React Native

Esempio non conforme

In questo esempio, TouchableOpacity è cliccabile, ma il componente annidato View ha accessible={true}, il che impedisce al genitore di acquisire il focus di accessibilità. Il View riceverà il focus al posto del TouchableOpacity cliccabile, ma non sarà annunciato come interattivo. Gli utenti delle tecnologie assistive sentiranno le informazioni sul prodotto, ma non sapranno che possono toccare per visualizzare i dettagli.

Scheda che riporta 'Prezzo del prodotto 10,00 $' con contorno di messa a fuoco all'interno
<TouchableOpacity
    accessibilityRole="button"
    style={styles.productCard}
    onPress={() => navigateTo("product")}
>
    <View accessible={true}>
        <Text>Product Price</Text>
        <Text>$10.00</Text>
    </View>
</TouchableOpacity>

Guida alla correzione: aggiungere proprietà di accessibilità

In questo esempio dopo la correzione, TouchableOpacity ha le proprietà di accessibilità appropriate impostate direttamente su di esso. Le proprietà accessible={true} e accessibilityRole="button" garantiscono che le tecnologie assistive lo annuncino come elemento interattivo, così che gli utenti comprendano il contenuto e sappiano che è possibile interagire con esso.

 Scheda con il testo 'Prezzo del prodotto 10,00 $' e contorno di messa a fuoco esterno
<TouchableOpacity
    accessible={true}
    accessibilityRole="button"
    style={styles.productCard}
    onPress={() => navigateTo("product")}
>
    <Text>Product Price</Text>
    <Text>$10.00</Text>
</TouchableOpacity>

Flutter

Esempio non conforme

Nell'esempio qui sotto, il GestureDetector funge da wrapper padre cliccabile per il Card, ma non è in grado di ottenere il focus da solo. Card funge da contenitore per i suoi elementi figli, quindi riceverà il focus e annuncerà tutto il contenuto dei nodi figli. Quando gli utenti delle tecnologie assistive si posizionano su Card, non verrà annunciato "Tocca due volte per attivare" all'utente, poiché Card in sé non è cliccabile, anche se il genitore GestureDetector lo è.

Scheda con la scritta 'Testo con genitore interattivo', con contorno di messa a fuoco interno
GestureDetector(
  onTap: () => ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text("Card clicked"),
        behavior: SnackBarBehavior.floating,
      )
  ),
  child: const Card(
    child: Padding(
      padding: EdgeInsets.all(16.0),
      child: Text(
        "Card with clickable parent"
      ),
    ),
  ),
);

Guida alla correzione: non utilizzi un wrapper GestureDetector

Qui, il InkWell funge da elemento figlio cliccabile del Card e avrà le stesse dimensioni del Card. Ora InkWell funge da contenitore che presenta tutto il contenuto testuale agli utenti di tecnologie assistive. Il risultato è un unico elemento cliccabile che annuncia « Tocca due volte per attivare » per indicare che è interattivo.

Scheda con etichetta «Testo con genitore cliccabile», con bordo di messa a fuoco esterno
Card(
    child: InkWell(
      onTap: () => ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text("Card clicked"),
            behavior: SnackBarBehavior.floating,
          )
      ),
      child: const Padding(
        padding: EdgeInsets.all(16.0),
        child: Text(
          "Text with clickable parent"
        ),
      ),
    ),
  )

Risorse

Deque University Course Pages (Subscription Required)

Altre risorse