Accessibility Label è il nome di un elemento dell'interfaccia che VoiceOver (iOS) o TalkBack (Android) pronunciano quando è attivo. In iOS, la proprietà si chiama accessibilityLabel, in Android — contentDescription per elementi che non contengono testo. Secondo Apple Developer Documentation, 2024, l'etichetta è il fondamento dell'accessibilità: senza di essa, l'utente non può identificare l'elemento. L'etichetta deve essere univoca nello schermo e riflettere l'essenza dell'elemento in un linguaggio chiaro.
Punti chiave
Accessibility Label è una proprietà stringa che definisce il nome di un elemento per le tecnologie assistive. Quando l'utente scorre lo schermo con VoiceOver attivato, il lettore dello schermo legge l'etichetta dell'elemento focalizzato. Senza etichetta, l'utente sente solo il tipo di elemento: “pulsante”, “immagine” — senza indicazione dello scopo.
Secondo Google I/O 2024, “Accessibility Testing”, il 35% delle violazioni critiche di accessibilità nelle applicazioni dello store sono correlate all'assenza o all'incorrettezza delle etichette. Accessibility Scanner su Android rileva l'assenza di etichetta come un errore di massima gravità.
Una limitazione fondamentale: l'etichetta non deve contenere il tipo di elemento. VoiceOver e TalkBack aggiungono automaticamente il ruolo (pulsante, intestazione, link) all'annuncio. Se l'etichetta contiene “Pulsante di invio”, l'utente sentirà: “Pulsante di invio, pulsante” — duplicazione.
WCAG 4.1.2 (livello A) richiede che ogni elemento dell'interfaccia utente abbia un nome, un ruolo e un valore determinabili a livello di codice. Accessibility Label fornisce il nome. Se l'etichetta è assente, il criterio è considerato violato e l'applicazione non supera la certificazione di base.
In iOS, accessibilityLabel è ereditato da tutti i UIView dal protocollo UIAccessibility. Se un elemento contiene testo (UIButton con titolo, UILabel con testo), l'etichetta viene automaticamente impostata su quel testo. Per UIImageView, controlli personalizzati e contenitori, l'etichetta deve essere impostata manualmente.
Esempio per una cella di tabella personalizzata:
class CustomTableViewCell: UITableViewCell {
let titleLabel = UILabel()
let priceLabel = UILabel()
override func awakeFromNib() {
super.awakeFromNib()
self.isAccessibilityElement = true
self.accessibilityLabel =
"\(titleLabel.text ?? "") - \(priceLabel.text ?? "")"
}
}
Per UIView personalizzate, puoi sovrascrivere il getter accessibilityLabel:
class RatingView: UIView {
var rating: Int = 5
override var accessibilityLabel: String? {
get { return "Valutazione: \(rating) su 5" }
set {}
}
}
Apple HIG, 2024 consiglia: se un elemento è composto da più sottoelementi (ad esempio, una carta prodotto con nome e prezzo), combinateli in un unico elemento di accessibilità con un'etichetta composita. Imposta isAccessibilityElement = true sul genitore e false sui figli.
Se UILabel usa NSAttributedString, accessibilityLabel per impostazione predefinita è uguale a .string (testo semplice). Se è necessario passare un valore semanticamente diverso (ad esempio, un'icona simbolo viene letta come “Stella” invece del carattere ★), imposta esplicitamente accessibilityLabel. VoiceOver non legge i caratteri Unicode in modo significativo.
In Android, contentDescription funge da etichetta per ImageView, ImageButton e viste personalizzate. Per TextView e Button con testo integrato, non è necessario impostare contentDescription — TalkBack legge il testo automaticamente.
Impostazione a livello di codice tramite Kotlin:
binding.iconStar.contentDescription = "Prodotto nei preferiti"
// Per View personalizzata con più elementi
binding.customCard.setContentDescription(
"\(title) per \(price)")
In XML per elementi decorativi:
<ImageView
android:contentDescription="@null"
android:src="@drawable/divider"
android:importantForAccessibility="no" />
La proprietà importantForAccessibility = “no” esclude completamente l'elemento dall'albero di accessibilità. In iOS, l'equivalente è isAccessibilityElement = false.
In Jetpack Compose, l'etichetta viene impostata tramite il modificatore semantics:
Image(
painter = painterResource(R.drawable.ic_search),
contentDescription = "Cerca prodotti",
modifier = Modifier.semantics {
contentDescription = "Cerca prodotti"
}
)
In Compose, contentDescription è un parametro obbligatorio per Image — senza di esso, il codice non viene compilato (avviso). Ciò migliora forzatamente l'accessibilità attraverso il design dell'API.
Accessibility Label risponde alla domanda “Cos'è questo elemento?”. Hint (accessibilityHint in iOS, testo aggiuntivo in contentDescription in Android) — “Cosa succederà interagendo?”. VoiceOver li annuncia in sequenza: prima Label, poi Hint.
Esempio per un pulsante di eliminazione:
Secondo Deque University, 2024, la corretta separazione di Label e Hint migliora il tasso di completamento delle attività per gli utenti VoiceOver del 28%. Gli utenti con disabilità cognitive dipendono particolarmente da Hint: quando non sono sicuri di premere “Elimina” senza spiegazione, il 40% rifiuta l'azione.
Un errore frequente: scrivere “Pulsante di eliminazione” in Label invece di “Elimina”. Il tipo di elemento (Pulsante) viene aggiunto automaticamente da VoiceOver tramite un tratto. Di conseguenza, l'utente sente: “Pulsante di eliminazione, pulsante” — duplicazione. Label corretto: “Elimina”, Hint: “Elimina la foto selezionata”.
La localizzazione delle etichette è obbligatoria — avviene tramite meccanismi standard: NSLocalizedString in iOS, risorse stringa @string/ in Android. Non impostare mai un'etichetta per concatenazione in inglese senza localizzazione.
Regole per una buona etichetta, basate su W3C WCAG 2.2:
Usa un glossario unico per le etichette in tutta l'applicazione. Se su uno schermo c'è scritto “Preferiti” e su un altro “Segnalibri”, l'utente è disorientato. Crea una tabella di terminologia di accessibilità — coordina con designer e localizzatori.
Per i campi di input (UITextField, EditText), l'etichetta deve corrispondere al placeholder o all'etichetta del campo. Tuttavia, il placeholder spesso scompare dopo l'inserimento del testo. Usa accessibilityLabel per il nome permanente e accessibilityValue per il contenuto corrente del campo — questo è lo standard WCAG 4.1.2. Soluzione: imposta accessibilityLabel staticamente (uguale all'etichetta del campo) e accessibilityValue dinamicamente (uguale al testo inserito). In iOS questo è automatico, ma per campi personalizzati — manualmente sovrascrivendo accessibilityValue. Verifica che VoiceOver legga: “Email, esempio@dominio.com, campo di testo” invece di “, campo di testo”.
I test automatizzati sono l'unico modo per garantire la correttezza delle etichette su tutti gli schermi. iOS fornisce XCUIApplication con accesso a .label, Android — AccessibilityCheckRule e setContentDescription.
Esempio di test per 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,
"Etichette duplicate trovate")
}
Esempio per Android con Espresso:
@Test
fun testButtonHasAccessibilityLabel() {
onView(withId(R.id.btnSubmit))
.check(matches(
withContentDescription(containsString("Invia"))
))
}
Test manuali: attiva VoiceOver (iOS) o TalkBack (Android) e scorri verso destra su tutti gli elementi dello schermo. Ogni elemento dovrebbe ricevere un annuncio significativo. Se senti solo “pulsante” o “immagine” — l'etichetta è assente.
Dopo aver impostato l'etichetta, gli utenti VoiceOver possono usare il rotore per la navigazione rapida: modalità “Pulsanti”, “Intestazioni”, “Link” e altre. Se l'etichetta è impostata correttamente, VoiceOver include l'elemento nella modalità del rotore corrispondente. Verifica che tutti i pulsanti siano visibili in modalità “Pulsanti”, tutte le intestazioni in “Intestazioni”.
L'etichetta influisce anche sulla ricerca di VoiceOver. L'utente può digitare una parola in modalità ricerca e VoiceOver sposterà lo fuoco sull'elemento con un'etichetta corrispondente. Pertanto, le etichette dovrebbero contenere parole chiave che l'utente cercherà.
Aggiungi il controllo delle etichette alla pipeline. Su iOS, usa XCUITest con fastlane scan. Su Android, usa Accessibility Test Framework con la regola AccessibilityCheckRule che rileva contentDescription vuoti. Questo previene regressioni durante l'unione di nuovi schermi.
Domande frequenti
Label identifica l'elemento (“Cerca”), Hint spiega il risultato dell'azione (“Apre lo schermo di ricerca”). VoiceOver annuncia Label immediatamente alla focalizzazione e Hint in modalità descrizioni dettagliate.
In iOS, UILabel ottiene automaticamente un accessibilityLabel uguale al suo testo. Non è necessaria alcuna configurazione aggiuntiva. In Android, TextView si comporta in modo simile.
Imposta isAccessibilityElement = true sulla vista genitore e sovrascrivi accessibilityLabel, restituendo il testo concatenato dagli elementi figli. Per componenti complessi, usa la concatenazione con un separatore.
Aggiungi contesto agli elementi ripetuti: “Acquista iPhone 15”, “Acquista iPhone 15 Pro”. Automatizza il controllo tramite test UI — raccogli tutte le etichette e verifica che non ci siano duplicati.
No. Per nascondere un elemento, usa isAccessibilityElement = false in iOS o importantForAccessibility = “no” in Android. Un'etichetta vuota non nasconde l'elemento — il lettore dello schermo leggerà “senza titolo”.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche