Accessibility Label είναι το όνομα ενός στοιχείου διεπαφής που το VoiceOver (iOS) ή το TalkBack (Android) εκφωνεί όταν εστιάζει. Στο iOS η ιδιότητα ονομάζεται accessibilityLabel, στο Android — contentDescription για στοιχεία που δεν περιέχουν κείμενο. Σύμφωνα με τα Apple Developer Documentation, 2024, η ετικέτα είναι η βάση της προσβασιμότητας: χωρίς αυτήν ο χρήστης δεν μπορεί να αναγνωρίσει το στοιχείο. Η ετικέτα πρέπει να είναι μοναδική εντός της οθόνης και να αντικατοπτρίζει την ουσία του στοιχείου με κατανοητό τρόπο.
Βασικά σημεία
Accessibility Label είναι μια ιδιότητα συμβολοσειράς που καθορίζει το όνομα του στοιχείου για υποστηρικτικές τεχνολογίες. Όταν ο χρήστης σύρει το δάχτυλο στην οθόνη με ενεργοποιημένο το VoiceOver, το screen reader διαβάζει το Label του στοιχείου που βρίσκεται σε εστίαση. Χωρίς ετικέτα, ο χρήστης ακούει μόνο τον τύπο του στοιχείου: “κουμπί”, “εικόνα” — χωρίς να αναφέρεται ο σκοπός.
Σύμφωνα με τα Google I/O 2024, “Accessibility Testing”, το 35% των κρίσιμων παραβιάσεων προσβασιμότητας σε εφαρμογές καταστημάτων σχετίζονται με την απουσία ή την εσφαλμένη χρήση Label. Το Accessibility Scanner στο Android ανιχνεύει την απουσία ετικέτας ως σφάλμα υψίστης σοβαρότητας.
Θεμελιώδης περιορισμός: το Label δεν πρέπει να περιέχει τον τύπο του στοιχείου. Το VoiceOver και το TalkBack προσθέτουν αυτόματα τον ρόλο (button, header, link) στην ανακοίνωση. Αν το Label περιέχει “Κουμπί αποστολής”, ο χρήστης θα ακούσει: “Κουμπί αποστολής, κουμπί” — διπλασιασμός.
Το WCAG 4.1.2 (επίπεδο A) απαιτεί κάθε στοιχείο διεπαφής χρήστη να έχει ένα όνομα (name), ρόλο (role) και τιμή (value) προσδιορίσιμο προγραμματικά. Το Accessibility Label παρέχει το name. Εάν το Label λείπει, το κριτήριο θεωρείται παραβιασμένο και η εφαρμογή δεν περνά τη βασική πιστοποίηση.
Στο iOS το accessibilityLabel κληρονομείται από όλα τα UIView μέσω του πρωτοκόλλου UIAccessibility. Εάν το στοιχείο περιέχει κείμενο (UIButton με title, UILabel με text), το Label ορίζεται αυτόματα ίσο με αυτό το κείμενο. Για UIImageView, προσαρμοσμένα controls και containers, το Label πρέπει να ορίζεται χειροκίνητα.
Παράδειγμα για προσαρμοσμένο κελί πίνακα:
class CustomTableViewCell: UITableViewCell {
let titleLabel = UILabel()
let priceLabel = UILabel()
override func awakeFromNib() {
super.awakeFromNib()
self.isAccessibilityElement = true
self.accessibilityLabel =
"\(titleLabel.text ?? "") - \(priceLabel.text ?? "")"
}
}
Για προσαρμοσμένα UIView μπορείτε να παρακάμψετε το getter accessibilityLabel:
class RatingView: UIView {
var rating: Int = 5
override var accessibilityLabel: String? {
get { return "Αξιολόγηση: \(rating) από 5" }
set {}
}
}
Apple HIG, 2024 συνιστά: αν το στοιχείο αποτελείται από πολλά υποστοιχεία (π.χ. κάρτα προϊόντος με όνομα και τιμή), συνδυάστε τα σε ένα accessibility-στοιχείο με σύνθετο Label. Ορίστε isAccessibilityElement = true στον γονέα και false στα παιδιά.
Εάν το UILabel χρησιμοποιεί NSAttributedString, το accessibilityLabel από προεπιλογή ισούται με .string (απλό κείμενο). Εάν χρειάζεται να μεταδώσετε μια σημασιολογικά διαφορετική τιμή (π.χ. ένα εικονίδιο-σύμβολο διαβάζεται ως “Αστέρι” αντί για το σύμβολο ★), ορίστε ρητά το accessibilityLabel. Το VoiceOver δεν διαβάζει σύμβολα Unicode με νόημα.
Στο Android το contentDescription εκτελεί τη λειτουργία Label για ImageView, ImageButton και προσαρμοσμένες View. Για TextView και Button με ενσωματωμένο κείμενο, δεν απαιτείται ορισμός contentDescription — το TalkBack διαβάζει το κείμενο αυτόματα.
Προγραμματικός ορισμός μέσω Kotlin:
binding.iconStar.contentDescription = "Προϊόν στα αγαπημένα"
// Για προσαρμοσμένη View με πολλαπλά στοιχεία
binding.customCard.setContentDescription(
"\(title) στο ποσό \(price)")
Σε XML για διακοσμητικά στοιχεία:
<ImageView
android:contentDescription="@null"
android:src="@drawable/divider"
android:importantForAccessibility="no" />
Η ιδιότητα importantForAccessibility = “no” αποκλείει εντελώς το στοιχείο από το δέντρο προσβασιμότητας. Στο iOS αντίστοιχο είναι το isAccessibilityElement = false.
Στο Jetpack Compose το Label ορίζεται μέσω του τροποποιητή semantics:
Image(
painter = painterResource(R.drawable.ic_search),
contentDescription = "Αναζήτηση προϊόντων",
modifier = Modifier.semantics {
contentDescription = "Αναζήτηση προϊόντων"
}
)
Στο Compose το contentDescription είναι υποχρεωτική παράμετρος για το Image, χωρίς αυτό ο κώδικας δεν μεταγλωττίζεται (warning). Αυτό βελτιώνει υποχρεωτικά την προσβασιμότητα μέσω του σχεδιασμού API.
Το Accessibility Label απαντά στην ερώτηση “Τι είναι αυτό το στοιχείο;”. Το Hint (accessibilityHint στο iOS, πρόσθετο κείμενο στο contentDescription στο Android) — “Τι θα συμβεί κατά την αλληλεπίδραση;”. Το VoiceOver τα εκφωνεί διαδοχικά: πρώτα το Label, μετά το Hint.
Παράδειγμα για κουμπί διαγραφής:
Σύμφωνα με τα Deque University, 2024, ο σωστός διαχωρισμός Label και Hint αυξάνει το ποσοστό επιτυχίας ολοκλήρωσης εργασιών για χρήστες VoiceOver κατά 28%. Οι χρήστες με γνωστικές διαταραχές είναι ιδιαίτερα εξαρτημένοι από το Hint: διακινδυνεύοντας να πατήσουν “Διαγραφή” χωρίς επεξήγηση, το 40% αποφεύγει την ενέργεια.
Συχνό λάθος: στο Label γράφουν “Κουμπί διαγραφής” αντί για “Διαγραφή”. Ο τύπος στοιχείου (Button) προστίθεται από το VoiceOver αυτόματα μέσω του trait. Ως αποτέλεσμα, ο χρήστης ακούει: “Κουμπί διαγραφής, κουμπί” — διπλασιασμός. Σωστό Label: “Διαγραφή”, Hint: “Θα διαγράψει την επιλεγμένη φωτογραφία”.
Η μετάφραση ετικετών είναι υποχρεωτική — γίνεται μέσω τυπικών μηχανισμών: NSLocalizedString στο iOS, πόροι συμβολοσειρών @string/ στο Android. Μην ορίζετε ποτέ Label με συνένωση στα αγγλικά χωρίς μετάφραση.
Κανόνες καλού Label, βασισμένοι στο W3C WCAG 2.2:
Χρησιμοποιήστε ενιαίο γλωσσάρι για Label στην εφαρμογή. Αν σε μία οθόνη γράφει “Αγαπημένα” και σε άλλη “Σελιδοδείκτες”, ο χρήστης αποπροσανατολίζεται. Δημιουργήστε έναν Πίνακα Όρων Προσβασιμότητας — συντονιστείτε με σχεδιαστές και μεταφραστές.
Για πεδία εισαγωγής (UITextField, EditText) το Label πρέπει να ταιριάζει με το placeholder ή την επικεφαλίδα του πεδίου. Ωστόσο, το placeholder συχνά κρύβεται μετά την εισαγωγή κειμένου. Χρησιμοποιήστε accessibilityLabel για μόνιμο όνομα και accessibilityValue για τρέχον περιεχόμενο πεδίου — αυτό είναι το πρότυπο WCAG 4.1.2. Λύση: ορίστε accessibilityLabel στατικά (ίσο με την επικεφαλίδα πεδίου) και accessibilityValue δυναμικά (ίσο με το εισαγόμενο κείμενο). Στο iOS αυτό γίνεται αυτόματα, αλλά για προσαρμοσμένα πεδία — χειροκίνητα μέσω παράκαμψης του accessibilityValue. Ελέγξτε ότι το VoiceOver διαβάζει: “Email, example@domain.com, πεδίο κειμένου” αντί για “, πεδίο κειμένου”.
Ο αυτοματοποιημένος έλεγχος είναι ο μόνος τρόπος να εγγυηθείτε την ορθότητα των Label σε όλες τις οθόνες. Το iOS παρέχει το XCUIApplication με πρόσβαση στο .label, το Android — το AccessibilityCheckRule και το setContentDescription.
Παράδειγμα δοκιμής για 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,
"Βρέθηκαν διπλότυπες ετικέτες Label")
}
Παράδειγμα για Android με Espresso:
@Test
fun testButtonHasAccessibilityLabel() {
onView(withId(R.id.btnSubmit))
.check(matches(
withContentDescription(containsString("Αποστολή"))
))
}
Χειροκίνητος έλεγχος: ενεργοποιήστε το VoiceOver (iOS) ή το TalkBack (Android) και μετακινηθείτε με χειρονομία δεξιά σε όλα τα στοιχεία της οθόνης. Κάθε στοιχείο πρέπει να λάβει μια ουσιαστική ανακοίνωση. Αν ακούτε μόνο “κουμπί” ή “εικόνα” — το Label λείπει.
Μετά τη ρύθμιση του Label, ο χρήστης VoiceOver μπορεί να χρησιμοποιήσει τον περιστροφέα για γρήγορη πλοήγηση: λειτουργίες “Κουμπιά”, “Επικεφαλίδες”, “Σύνδεσμοι” και άλλες. Αν το Label έχει οριστεί σωστά, το VoiceOver συμπεριλαμβάνει το στοιχείο στην αντίστοιχη λειτουργία του περιστροφέα. Ελέγξτε ότι όλα τα κουμπιά είναι ορατά στη λειτουργία “Κουμπιά”, όλες οι επικεφαλίδες στη λειτουργία “Επικεφαλίδες”.
Το Label επηρεάζει επίσης την αναζήτηση VoiceOver. Ο χρήστης μπορεί να πληκτρολογήσει μια λέξη στη λειτουργία αναζήτησης και το VoiceOver θα μετακινήσει την εστίαση στο στοιχείο με το αντίστοιχο Label. Γι' αυτό το Label πρέπει να περιέχει λέξεις-κλειδιά με τις οποίες ο χρήστης θα αναζητήσει το στοιχείο.
Προσθέστε τον έλεγχο Label στο pipeline. Στο iOS χρησιμοποιήστε XCUITest με fastlane scan. Στο Android — Accessibility Test Framework με τον κανόνα AccessibilityCheckRule που ανιχνεύει κενά contentDescription. Αυτό αποτρέπει παλινδρομήσεις κατά τη συγχώνευση νέων οθονών.
Συχνές ερωτήσεις
Το Label αναγνωρίζει το στοιχείο (“Αναζήτηση”), το Hint εξηγεί το αποτέλεσμα της ενέργειας (“Θα ανοίξει την οθόνη αναζήτησης”). Το VoiceOver εκφωνεί το Label αμέσως κατά την εστίαση και το Hint σε λειτουργία λεπτομερών περιγραφών.
Στο iOS το UILabel λαμβάνει αυτόματα accessibilityLabel ίσο με το κείμενό του. Δεν χρειάζεται επιπλέον ορισμός. Στο Android το TextView συμπεριφέρεται ανάλογα.
Ορίστε isAccessibilityElement = true στη γονική View και παρακάμψτε το accessibilityLabel επιστρέφοντας συνενωμένο κείμενο από τα θυγατρικά στοιχεία. Για σύνθετα στοιχεία χρησιμοποιήστε συνένωση με διαχωριστικό.
Προσθέστε πλαίσιο σε επαναλαμβανόμενα στοιχεία: “Αγορά iPhone 15”, “Αγορά iPhone 15 Pro”. Αυτοματοποιήστε τον έλεγχο μέσω UI tests — συλλέξτε όλα τα Label και ελέγξτε την απουσία διπλοτύπων.
Όχι. Για απόκρυψη στοιχείου χρησιμοποιήστε isAccessibilityElement = false στο iOS ή importantForAccessibility = “no” στο Android. Ένα κενό Label δεν κρύβει το στοιχείο — το screen reader θα διαβάσει “χωρίς όνομα”.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης