Accessibility Trait — είναι μια ιδιότητα ενός στοιχείου iOS που καθορίζει το ρόλο και τη συμπεριφορά του για το VoiceOver. Το trait λέει στον αναγνώστη οθόνης πώς πρέπει να εκφωνηθεί το στοιχείο και ποιες χειρονομίες είναι διαθέσιμες: αν είναι κουμπί, επικεφαλίδα, σύνδεσμος ή πεδίο αναζήτησης. Σύμφωνα με το Apple UIAccessibilityTraits, 2024, το σύστημα υποστηρίζει 15+ σταθερές που μπορούν να συνδυαστούν με μάσκα bit. Το σωστά επιλεγμένο trait εξοικονομεί έως και 50% του χρόνου πλοήγησης για χρήστες του VoiceOver.
Βασικά Σημεία
Accessibility Trait — μια σημαία που τοποθετείται στο στοιχείο UIView για να υποδείξει το σημασιολογικό του ρόλο για το VoiceOver. Το trait είναι ένα από τα τρία συστατικά της τριάδας accessibility της Apple: Label (όνομα), Hint (περιγραφή), Trait (ρόλος). Το iOS χρησιμοποιεί τη μάσκα bit UIAccessibilityTraits (UInt64), όπου κάθε bit αντιστοιχεί σε ένα συγκεκριμένο ρόλο. Το VoiceOver διαβάζει το ρόλο μετά το Label και το Hint: “Κουμπί Αποστολή. Θα ανοίξει τη φόρμα” — “Κουμπί” προστέθηκε χάρη στο trait UIAccessibilityTraitButton.
Από προεπιλογή, το UIButton λαμβάνει UIAccessibilityTraitButton, το UILabel — UIAccessibilityTraitStaticText, το UIImageView — UIAccessibilityTraitImage. Κατά τη χρήση προσαρμοσμένων στοιχείων ελέγχου, ο προγραμματιστής υποχρεούται να ορίσει χειροκίνητα το trait. Οι Apple Human Interface Guidelines, 2024, το αποκαλούν “ένα από τα πιο κρίσιμα βήματα για τη διασφάλιση της προσβασιμότητας”.
Χωρίς το σωστό trait, ο χρήστης δεν γνωρίζει ποια χειρονομία να εφαρμόσει: απλό άγγιγμα (ενεργοποίηση κουμπιού), διπλό άγγιγμα (μεγέθυνση) ή χειρονομία σύρσης (διακόπτης). Το trait καθορίζει ποιες χειρονομίες θα ενεργοποιήσει το VoiceOver στο στοιχείο.
UIAccessibilityTraits — είναι typealias UInt64. Κάθε trait είναι μια σταθερά όπου έχει οριστεί ακριβώς ένα bit. Για παράδειγμα, UIAccessibilityTraitButton = 0x0000000000000001, UIAccessibilityTraitLink = 0x0000000000000002, UIAccessibilityTraitHeader = 0x0000000000000008. Ο συνδυασμός επιτυγχάνεται μέσω bitwise OR: 0x0001 | 0x0008 = 0x0009. Το VoiceOver αναλύει τη μάσκα και καθορίζει τη συμπεριφορά.
Το iOS παρέχει περισσότερες από 15 σταθερές traits. Ας εξετάσουμε τις κύριες, που χρησιμοποιούνται στο 90% των σεναρίων:
| Trait | Σταθερά | Συμπεριφορά VoiceOver |
|---|---|---|
| Button | UIAccessibilityTraitButton | Ενεργοποίηση με διπλό άγγιγμα |
| Header | UIAccessibilityTraitHeader | Γρήγορη πλοήγηση μέσω επικεφαλίδων |
| Link | UIAccessibilityTraitLink | Ενεργοποίηση ως σύνδεσμος |
| StaticText | UIAccessibilityTraitStaticText | Μόνο ανάγνωση, χωρίς ενεργοποίηση |
| SearchField | UIAccessibilityTraitSearchField | Πεδίο αναζήτησης με ειδική συμπεριφορά |
| Image | UIAccessibilityTraitImage | Εικόνα, χωρίς χειρονομία ενεργοποίησης |
| Selected | UIAccessibilityTraitSelected | Κατάσταση “επιλεγμένο” |
| PlaysSound | UIAccessibilityTraitPlaysSound | Αναπαράγει ήχο κατά την ενεργοποίηση |
| KeyboardKey | UIAccessibilityTraitKeyboardKey | Πλήκτρο πληκτρολογίου |
| TabBar | UIAccessibilityTraitTabBar | Στοιχείο γραμμής καρτελών |
Οι σταθερές είναι διαθέσιμες στο UIKit από το iOS 3.0. Στο iOS 14+ προστέθηκε υποστήριξη για UIAccessibilityTraits στο SwiftUI μέσω του τροποποιητή .accessibilityAddTraits().
UIAccessibilityTraitAdjustable — για ρυθμιζόμενες τιμές (ρυθμιστικά, επιλογείς, ρυθμιστικά έντασης). Το VoiceOver επιτρέπει σύρση προς τα πάνω/κάτω για αλλαγή της τιμής με βήμα που ορίζεται μέσω των accessibilityIncrement και accessibilityDecrement. UIAccessibilityTraitUpdatesFrequently — για στοιχεία με συχνά μεταβαλλόμενη τιμή (χρονόμετρο, δείκτης φόρτωσης). Το VoiceOver δεν διαβάζει την τιμή σε κάθε αλλαγή, αλλά κάνει παύση. UIAccessibilityTraitAllowsDirectInteraction — για στοιχεία με τα οποία ο χρήστης μπορεί να αλληλεπιδράσει απευθείας (πληκτρολόγιο, εργαλείο σχεδίασης), παρακάμπτοντας τις χειρονομίες VoiceOver.
Ένα στοιχείο μπορεί να έχει πολλαπλά traits ταυτόχρονα — ο συνδυασμός καθορίζεται μέσω bitwise OR (|). Παράδειγμα: ένα κουμπί που είναι επί του παρόντος επιλεγμένο — Button | Selected. Το VoiceOver θα πει: “Επιλεγμένο. Φιλτραρισμένο κατά τιμή. Κουμπί”.
Ορισμός traits σε κώδικα:
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)
// Ή μέσω μάσκας:
filterButton.accessibilityTraits = [.button, .selected]
Για προσαρμοσμένα UIView όπου το trait δεν έχει οριστεί από προεπιλογή:
class CustomToggle: UIControl {
override var accessibilityTraits: UIAccessibilityTraits {
get {
if isOn {
return [.button, .selected]
} else {
return .button
}
}
set {}
}
}
Κανόνας συνδυασμού: όχι περισσότερα από 3-4 traits ανά στοιχείο. Τα υπερβολικά traits (π.χ. Button + Link + Header) καθιστούν την ανακοίνωση του VoiceOver πολύ μεγάλη και μπερδεμένη. Σύμφωνα με την Apple, “κάθε επιπλέον ιδιότητα αυξάνει το γνωστικό φορτίο του χρήστη”.
Στο SwiftUI, τα traits ορίζονται μέσω των τροποποιητών .accessibilityAddTraits() και .accessibilityRemoveTraits(). Παράδειγμα: Text(“Επικεφαλίδα”).font(.largeTitle).accessibilityAddTraits(.isHeader). Ο τροποποιητής .isHeader προσθέτει UIAccessibilityTraitHeader. Λίστα SwiftUI traits: .isButton, .isHeader, .isLink, .isSelected, .isImage, .isSearchField, .isKeyboardKey, .isStaticText, .isSummaryElement, .isToggle, .playsSound, .startsMediaSession, .updatesFrequently, .allowsDirectInteraction, .causesPageTurn, .isModal, .tabBar.
StaticText αντί για Button — ένα προσαρμοσμένο στοιχείο ελέγχου που μοιάζει οπτικά με κουμπί λαμβάνει από προεπιλογή το trait StaticText. Το VoiceOver δεν προσφέρει χειρονομία ενεργοποίησης, ο χρήστης δεν μπορεί να “πατήσει” το στοιχείο. Λύση: ορίστε ρητά το .button.
Image χωρίς trait — UIImageView με ενεργοποιημένη προσβασιμότητα λαμβάνει το trait Image, ακόμα κι αν στην πραγματικότητα είναι ένα κουμπί για μεγέθυνση φωτογραφίας. Ορίστε .button και Label “Μεγέθυνση φωτογραφίας”. Σύμφωνα με το WWDC 2023, “Deliver an Exceptional Accessibility Experience”, το 40% των παλινδρομήσεων προσβασιμότητας σε νέες εκδόσεις εφαρμογών προκαλείται ακριβώς από την ασυμφωνία trait.
Header σε κάθε στοιχείο — το trait Header προορίζεται για δομικές επικεφαλίδες οθόνης. Εάν κάνετε κάθε UILabel επικεφαλίδα, ο περιστροφέας VoiceOver στη λειτουργία “Επικεφαλίδες” θα γίνει άχρηστος — θα σταματά σε κάθε λέξη.
Συχνή αιτία απώλειας trait — ανακατασκευή: ο προγραμματιστής αντικαθιστά το UIButton με UIControl για προσαρμοσμένη εμφάνιση. Το UIButton λαμβάνει αυτόματα το trait Button, το UIControl — όχι. Μετά την ανακατασκευή πρέπει να οριστεί ρητά accessibilityTraits = .button. Προσθέστε έναν έλεγχο στην ανασκόπηση κώδικα: “Εάν αντικαταστήσατε το UIButton με UIControl — ελέγξτε το trait”.
Για στοιχεία με μεταβαλλόμενη κατάσταση (π.χ. κουμπί like) το trait πρέπει να αλλάζει δυναμικά. Στην κατάσταση “δεν μου αρέσει” — Button, στην κατάσταση “μου αρέσει” — Button + Selected + Image (εάν υπάρχει εικονίδιο). Το VoiceOver αλλάζει την ανακοίνωση: “Μου αρέσει. Κουμπί” έναντι “Επιλεγμένο. Μου αρέσει. Κουμπί”. Χρησιμοποιήστε το accessibilityValue για τη μεταφορά της κατάστασης, εάν το trait Selected δεν είναι επαρκές. Ισχύει για κουμπιά εγγραφής, αγαπημένων, φίλτρων και διακοπτών.
Στο Android δεν υπάρχει άμεσο αντίστοιχο των traits. Αντί για μάσκα bit χρησιμοποιούνται:
Για προσαρμοσμένα View στο Android πρέπει να γίνει παράκαμψη του onInitializeAccessibilityNodeInfo:
class CustomButton @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : View(context, attrs) {
override fun onInitializeAccessibilityNodeInfo(
info: AccessibilityNodeInfo
) {
super.onInitializeAccessibilityNodeInfo(info)
info.className = "android.widget.Button"
info.isClickable = true
}
}
Οι προγραμματιστές Flutter πρέπει να χρησιμοποιούν την παράμετρο semanticsRole στο widget Semantics: button, header, image, link, textField και άλλα. Επιπλέον, είναι διαθέσιμα τα semanticsLabel και semanticsHint — το πλήρες αντίστοιχο της τριάδας iOS Label + Hint + Trait.
Για εκδόσεις web εφαρμογών κινητών (PWA, WebView) χρησιμοποιείται το χαρακτηριστικό role από το WAI-ARIA: role="button", role="heading", role="link". Αυτό είναι το άμεσο αντίστοιχο του accessibilityTraits. Σε υβριδικές εφαρμογές ελέγξτε ότι το WebView μεταφέρει τους ρόλους ARIA στο εγγενές επίπεδο προσβασιμότητας. Για αυτό, χρησιμοποιήστε το πρωτόκολλο UIAccessibilityContainerDataTable στο iOS ή το setAccessibilityDelegate στο Android. Το WebView με ενεργοποιημένο JavaScript μπορεί να μην μεταφέρει σωστά τους ρόλους ARIA — δοκιμάστε ξεχωριστά.
Στο Android μπορούν να προστεθούν προσαρμοσμένες ενέργειες στο AccessibilityNodeInfo: AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK και ACTION_LONG_CLICK. Αυτό είναι το αντίστοιχο του trait Button με πρόσθετες χειρονομίες. Για ρυθμιστικά χρησιμοποιήστε ACTION_SET_PROGRESS — αντίστοιχο του Adjustable. Για Spinner και DatePicker — ACTION_SET_SELECTION, ACTION_SET_DATE και ACTION_SET_TIME.
Xcode Accessibility Inspector — το κύριο εργαλείο για iOS: επιλέξτε το στοιχείο και δείτε το πεδίο Traits. Θα εμφανίσει τη λίστα των ορισμένων traits. Ο περιστροφέας VoiceOver στη λειτουργία “Στοιχεία” επιτρέπει τη διέλευση από όλα τα στοιχεία ελέγχου της οθόνης.
Αυτοματοποιημένη δοκιμή σε Swift για έλεγχο trait:
func testSubmitButtonTrait() {
let app = XCUIApplication()
app.launch()
let submitButton = app.buttons["Αποστολή"]
XCTAssertTrue(submitButton.isEnabled)
// Το XCUIElement δεν παρέχει άμεση πρόσβαση στα traits
// Έλεγχος μέσω ενεργοποίησης χειρονομίας
submitButton.tap()
XCTAssertTrue(app.staticTexts["Η φόρμα στάλθηκε"].exists)
}
Χειροκίνητος έλεγχος μέσω VoiceOver: ενεργοποιήστε το VoiceOver, μετακινήστε το δάχτυλο στο στοιχείο, αγγίξτε δύο φορές — το στοιχείο θα πρέπει να ενεργοποιηθεί, εάν είναι Button. Εάν το στοιχείο δεν αντιδρά στο διπλό άγγιγμα, το trait είναι λανθασμένο. Χρησιμοποιήστε τη χειρονομία Rotor για εναλλαγή μεταξύ λειτουργιών (“Επικεφαλίδες”, “Σύνδεσμοι”, “Κουμπιά”) — κάθε λειτουργία θα εμφανίζει μόνο στοιχεία με το αντίστοιχο trait.
Πριν από το iOS 14, οι δοκιμές μονάδας δεν είχαν άμεση πρόσβαση στο accessibilityTraits. Από το iOS 14 και μετά, η ιδιότητα είναι διαθέσιμη: XCTAssertEqual(customButton.accessibilityTraits, .button). Χρησιμοποιήστε αυτό σε αρθρωτές δοκιμές για έλεγχο προσαρμοσμένων στοιχείων ελέγχου. Συνιστάται να δοκιμάζετε κάθε νέο προσαρμοσμένο UIView για ορθότητα trait, ειδικά μετά από ανακατασκευή ή αλλαγή γονικής κλάσης.
Συχνές Ερωτήσεις
Έως 3-4 traits ανά στοιχείο. Ο μεγαλύτερος αριθμός καθιστά την ανακοίνωση VoiceOver περιττή. Χρησιμοποιήστε συνδυασμούς: Button + Selected, Header + StaticText.
UIAccessibilityTraitButton. Το iOS το ορίζει αυτόματα για όλες τις περιπτώσεις UIButton. Εάν κληρονομείτε από UIView και προσομοιώνετε κουμπί, το trait πρέπει να οριστεί χειροκίνητα.
Ναι, UIAccessibilityTraitAdjustable — για στοιχεία με ρυθμιζόμενη τιμή (ρυθμιστικά, επιλογείς, μετρητές). Το VoiceOver επιτρέπει σύρση προς τα πάνω/κάτω για αλλαγή της τιμής και διαβάζει την τρέχουσα κατάσταση.
Χρησιμοποιήστε τον τροποποιητή .accessibilityAddTraits(): Text(“Επικεφαλίδα”).font(.title).accessibilityAddTraits(.isHeader). Η μέθοδος λειτουργεί σε iOS 14+.
Το VoiceOver θα εκχωρήσει το trait None. Το στοιχείο δεν θα λάβει ρόλο — ο αναγνώστης οθόνης θα διαβάσει μόνο το Label χωρίς να καθορίσει τον τύπο. Ο χρήστης δεν θα γνωρίζει εάν η χειρονομία ενεργοποίησης είναι διαθέσιμη.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης