Accessibility Trait — adalah properti elemen iOS yang menentukan peran dan perilakunya untuk VoiceOver. Trait memberi tahu pembaca layar bagaimana elemen harus disuarakan dan gerakan apa yang tersedia: apakah itu tombol, header, tautan atau kolom pencarian. Menurut Apple UIAccessibilityTraits, 2024, sistem mendukung 15+ konstanta yang dapat digabungkan dengan mask bit. Trait yang dipilih dengan benar menghemat hingga 50% waktu navigasi bagi pengguna VoiceOver.
Poin Penting
Accessibility Trait — sebuah flag yang dipasang pada elemen UIView untuk menunjukkan peran semantiknya bagi VoiceOver. Trait adalah salah satu dari tiga komponen triad accessibility Apple: Label (nama), Hint (deskripsi), Trait (peran). iOS menggunakan mask bit UIAccessibilityTraits (UInt64), di mana setiap bit sesuai dengan peran tertentu. VoiceOver membaca peran setelah Label dan Hint: “Tombol Kirim. Akan membuka formulir” — “Tombol” ditambahkan berkat trait UIAccessibilityTraitButton.
Secara default, UIButton mendapatkan UIAccessibilityTraitButton, UILabel — UIAccessibilityTraitStaticText, UIImageView — UIAccessibilityTraitImage. Saat menggunakan kontrol khusus, pengembang wajib mengatur trait secara manual. Apple Human Interface Guidelines, 2024, menyebut ini “salah satu langkah paling kritis dalam memastikan accessibility”.
Tanpa trait yang benar, pengguna tidak tahu gerakan mana yang harus diterapkan: sentuhan tunggal (aktivasi tombol), sentuhan ganda (perbesar) atau gerakan gesek (sakelar). Trait menentukan gerakan mana yang akan diaktifkan VoiceOver pada elemen.
UIAccessibilityTraits — adalah typealias UInt64. Setiap trait adalah konstanta di mana tepat satu bit diatur. Misalnya UIAccessibilityTraitButton = 0x0000000000000001, UIAccessibilityTraitLink = 0x0000000000000002, UIAccessibilityTraitHeader = 0x0000000000000008. Kombinasi dicapai melalui OR bitwise: 0x0001 | 0x0008 = 0x0009. VoiceOver menganalisis mask dan menentukan perilaku.
iOS menyediakan lebih dari 15 konstanta trait. Mari kita lihat yang utama, yang digunakan dalam 90% skenario:
| Trait | Konstanta | Perilaku VoiceOver |
|---|---|---|
| Button | UIAccessibilityTraitButton | Aktivasi dengan sentuhan ganda |
| Header | UIAccessibilityTraitHeader | Navigasi cepat melalui header |
| Link | UIAccessibilityTraitLink | Aktivasi sebagai tautan |
| StaticText | UIAccessibilityTraitStaticText | Hanya baca, tanpa aktivasi |
| SearchField | UIAccessibilityTraitSearchField | Kolom pencarian dengan perilaku khusus |
| Image | UIAccessibilityTraitImage | Gambar, tanpa gerakan aktivasi |
| Selected | UIAccessibilityTraitSelected | Status “dipilih” |
| PlaysSound | UIAccessibilityTraitPlaysSound | Memutar suara saat aktivasi |
| KeyboardKey | UIAccessibilityTraitKeyboardKey | Tombol keyboard |
| TabBar | UIAccessibilityTraitTabBar | Elemen bilah tab |
Konstanta tersedia di UIKit sejak iOS 3.0. Di iOS 14+ dukungan untuk UIAccessibilityTraits di SwiftUI ditambahkan melalui pengubah .accessibilityAddTraits().
UIAccessibilityTraitAdjustable — untuk nilai yang dapat disesuaikan (penggeser, pemilih, penggeser volume). VoiceOver memungkinkan geser ke atas/bawah untuk mengubah nilai dengan langkah yang ditentukan melalui accessibilityIncrement dan accessibilityDecrement. UIAccessibilityTraitUpdatesFrequently — untuk elemen dengan nilai yang sering berubah (timer, indikator pemuatan). VoiceOver tidak membaca nilai pada setiap perubahan, tetapi mengambil jeda. UIAccessibilityTraitAllowsDirectInteraction — untuk elemen yang dapat berinteraksi langsung dengan pengguna (keyboard, alat gambar), melewati gerakan VoiceOver.
Satu elemen dapat memiliki beberapa trait secara bersamaan — kombinasi ditentukan dengan OR bitwise (|). Contoh: tombol yang saat ini dipilih — Button | Selected. VoiceOver akan mengatakan: “Dipilih. Difilter berdasarkan harga. Tombol”.
Mengatur trait dalam kode:
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)
// Atau melalui mask:
filterButton.accessibilityTraits = [.button, .selected]
Untuk UIView khusus di mana trait tidak diatur secara default:
class CustomToggle: UIControl {
override var accessibilityTraits: UIAccessibilityTraits {
get {
if isOn {
return [.button, .selected]
} else {
return .button
}
}
set {}
}
}
Aturan penggabungan: tidak lebih dari 3-4 trait per elemen. Trait yang berlebihan (misalnya Button + Link + Header) membuat pengumuman VoiceOver terlalu panjang dan membingungkan. Menurut Apple, “setiap properti tambahan meningkatkan beban kognitif pengguna”.
Di SwiftUI trait diatur melalui pengubah .accessibilityAddTraits() dan .accessibilityRemoveTraits(). Contoh: Text(“Judul”).font(.largeTitle).accessibilityAddTraits(.isHeader). Pengubah .isHeader menambahkan UIAccessibilityTraitHeader. Daftar trait SwiftUI: .isButton, .isHeader, .isLink, .isSelected, .isImage, .isSearchField, .isKeyboardKey, .isStaticText, .isSummaryElement, .isToggle, .playsSound, .startsMediaSession, .updatesFrequently, .allowsDirectInteraction, .causesPageTurn, .isModal, .tabBar.
StaticText bukan Button — kontrol khusus yang secara visual terlihat seperti tombol mendapatkan trait StaticText secara default. VoiceOver tidak menawarkan gerakan aktivasi, pengguna tidak dapat “menekan” elemen. Solusi: atur .button secara eksplisit.
Image tanpa trait — UIImageView dengan accessibility diaktifkan mendapatkan trait Image, meskipun sebenarnya itu adalah tombol untuk memperbesar foto. Tetapkan .button dan Label “Perbesar foto”. Menurut WWDC 2023, “Deliver an Exceptional Accessibility Experience”, 40% regresi accessibility di versi baru aplikasi disebabkan tepat oleh ketidakcocokan trait.
Header pada setiap elemen — trait Header ditujukan untuk header struktural layar. Jika Anda menjadikan setiap UILabel sebagai header, rotor VoiceOver dalam mode “Header” akan menjadi tidak berguna — akan berhenti di setiap kata.
Untuk elemen dengan status yang berubah (misalnya tombol suka) trait harus berubah secara dinamis. Dalam status “tidak disukai” — Button, dalam status “disukai” — Button + Selected + Image (jika ada ikon). VoiceOver mengubah pengumuman: “Suka. Tombol” vs “Dipilih. Suka. Tombol”. Gunakan accessibilityValue untuk menyampaikan status jika trait Selected tidak mencukupi. Berlaku untuk tombol langganan, favorit, filter dan sakelar.
Di Android tidak ada analog langsung untuk trait. Sebagai pengganti mask bit digunakan:
Untuk View khusus di Android perlu menimpa 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
}
}
Pengembang Flutter harus menggunakan parameter semanticsRole di widget Semantics: button, header, image, link, textField dan lainnya. Selain itu tersedia semanticsLabel dan semanticsHint — analog lengkap dari triad iOS Label + Hint + Trait.
Untuk versi web aplikasi mobile (PWA, WebView) digunakan atribut role dari WAI-ARIA: role="button", role="heading", role="link". Ini adalah analog langsung dari accessibilityTraits. Di aplikasi hibrid periksa apakah WebView meneruskan peran ARIA ke lapisan accessibility native. Untuk ini gunakan protokol UIAccessibilityContainerDataTable di iOS atau setAccessibilityDelegate di Android. WebView dengan JavaScript aktif mungkin tidak meneruskan peran ARIA dengan benar — uji secara terpisah.
Di Android dapat menambahkan tindakan khusus ke AccessibilityNodeInfo: AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK dan ACTION_LONG_CLICK. Ini adalah analog trait Button dengan gerakan tambahan. Untuk penggeser gunakan ACTION_SET_PROGRESS — analog Adjustable. Untuk Spinner dan DatePicker — ACTION_SET_SELECTION, ACTION_SET_DATE dan ACTION_SET_TIME.
Xcode Accessibility Inspector — alat utama untuk iOS: pilih elemen dan lihat bidang Traits. Ini akan menampilkan daftar trait yang diatur. Rotor VoiceOver dalam mode “Elemen” memungkinkan melewati semua kontrol layar.
Tes otomatis di Swift untuk memeriksa trait:
func testSubmitButtonTrait() {
let app = XCUIApplication()
app.launch()
let submitButton = app.buttons["Kirim"]
XCTAssertTrue(submitButton.isEnabled)
// XCUIElement tidak menyediakan akses langsung ke trait
// Pemeriksaan melalui aktivasi gerakan
submitButton.tap()
XCTAssertTrue(app.staticTexts["Formulir terkirim"].exists)
}
Pemeriksaan manual melalui VoiceOver: aktifkan VoiceOver, gerakkan jari ke elemen, sentuh dua kali — elemen harus aktif jika itu Button. Jika elemen tidak bereaksi terhadap sentuhan ganda, trait salah. Gunakan gerakan Rotor untuk beralih antar mode (“Header”, “Tautan”, “Tombol”) — setiap mode hanya akan menampilkan elemen dengan trait yang sesuai.
Sebelum iOS 14, pengujian unit tidak memiliki akses langsung ke accessibilityTraits. Mulai iOS 14, properti tersedia: XCTAssertEqual(customButton.accessibilityTraits, .button). Gunakan ini dalam pengujian modular untuk memeriksa kontrol khusus. Disarankan untuk menguji setiap UIView khusus baru untuk kebenaran trait, terutama setelah refactoring atau perubahan kelas induk.
Pertanyaan yang Sering Diajukan
Hingga 3-4 trait per elemen. Jumlah yang lebih besar membuat pengumuman VoiceOver berlebihan. Gunakan kombinasi: Button + Selected, Header + StaticText.
UIAccessibilityTraitButton. iOS secara otomatis mengaturnya untuk semua instance UIButton. Jika Anda mewarisi dari UIView dan meniru tombol, trait harus diatur secara manual.
Ya, UIAccessibilityTraitAdjustable — untuk elemen dengan nilai yang dapat disesuaikan (penggeser, pemilih, penghitung). VoiceOver memungkinkan geser ke atas/bawah untuk mengubah nilai dan membaca status saat ini.
Gunakan pengubah .accessibilityAddTraits(): Text(“Judul”).font(.title).accessibilityAddTraits(.isHeader). Metode ini bekerja di iOS 14+.
VoiceOver akan menetapkan trait None. Elemen tidak akan mendapatkan peran — pembaca layar hanya akan membaca Label tanpa menyebutkan tipenya. Pengguna tidak akan tahu apakah gerakan aktivasi tersedia.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga