Accessibility Trait, VoiceOver için bir iOS öğesinin rolünü ve davranışını belirleyen bir özelliktir. Trait, ekran okuyucuya öğenin nasıl seslendirileceğini ve hangi hareketlerin kullanılabileceğini (düğme, başlık, bağlantı veya arama alanı olup olmadığını) söyler. Apple UIAccessibilityTraits, 2024'e göre sistem, bit maskesi kullanılarak birleştirilebilen 15'ten fazla sabiti destekler. Doğru seçilmiş bir trait, VoiceOver kullanıcıları için gezinme süresinden %50'ye kadar tasarruf sağlar.
Önemli Noktalar
Accessibility Trait, VoiceOver'a anlamsal rolünü belirtmek için bir UIView öğesinde ayarlanan bir bayraktır. Trait, Apple'ın erişilebilirlik üçlüsünün üç bileşeninden biridir: Label (ad), Hint (açıklama), Trait (rol). iOS, her bitin belirli bir role karşılık geldiği UIAccessibilityTraits bit maskesini (UInt64) kullanır. VoiceOver, Label ve Hint'ten sonra rolü okur: “Gönder Düğmesi. Bir form açacak” — UIAccessibilityTraitButton trait sayesinde “Düğme” eklenir.
Varsayılan olarak, UIButton UIAccessibilityTraitButton alır, UILabel UIAccessibilityTraitStaticText alır, UIImageView UIAccessibilityTraitImage alır. Özel kontroller kullanılırken, geliştiricinin traiti manuel olarak ayarlaması gerekir. Apple Human Interface Guidelines, 2024, bunu “erişilebilirliği sağlamanın en kritik adımlarından biri” olarak adlandırır.
Doğru trait olmadan, kullanıcı hangi hareketi uygulayacağını bilemez: tek dokunuş (düğme etkinleştirme), çift dokunuş (yakınlaştırma) veya kaydırma hareketi (değiştirme). Trait, öğede hangi VoiceOver hareketlerinin etkinleştirileceğini belirler.
UIAccessibilityTraits bir typealias UInt64'tür. Her trait, tam olarak bir biti ayarlanmış bir sabittir. Örneğin, UIAccessibilityTraitButton = 0x0000000000000001, UIAccessibilityTraitLink = 0x0000000000000002, UIAccessibilityTraitHeader = 0x0000000000000008. Kombinasyonlar, bit düzeyinde VEYA ile elde edilir: 0x0001 | 0x0008 = 0x0009. VoiceOver maskeyi analiz eder ve davranışı belirler.
iOS, 15'ten fazla trait sabiti sağlar. %90 senaryoda kullanılan ana türleri inceleyelim:
| Trait | Sabit | VoiceOver Davranışı |
|---|---|---|
| Button | UIAccessibilityTraitButton | Çift dokunuşla etkinleştirme |
| Header | UIAccessibilityTraitHeader | Başlıklara göre hızlı gezinme |
| Link | UIAccessibilityTraitLink | Bağlantı olarak etkinleştirme |
| StaticText | UIAccessibilityTraitStaticText | Salt okunur, etkinleştirme yok |
| SearchField | UIAccessibilityTraitSearchField | Özel davranışlı arama alanı |
| Image | UIAccessibilityTraitImage | Resim, etkinleştirme hareketi yok |
| Selected | UIAccessibilityTraitSelected | “Seçili” durumu |
| PlaysSound | UIAccessibilityTraitPlaysSound | Etkinleştirmede ses çalar |
| KeyboardKey | UIAccessibilityTraitKeyboardKey | Klavye tuşu |
| TabBar | UIAccessibilityTraitTabBar | Sekme çubuğu öğesi |
Sabitler, iOS 3.0'dan beri UIKit'te mevcuttur. iOS 14+, .accessibilityAddTraits() değiştiricisi aracılığıyla SwiftUI'de UIAccessibilityTraits desteğini eklemiştir.
UIAccessibilityTraitAdjustable — ayarlanabilir değerler için (kaydırıcılar, seçiciler, ses kaydırıcıları). VoiceOver, accessibilityIncrement ve accessibilityDecrement ile tanımlanan bir adımla değeri değiştirmek için yukarı/aşağı kaydırmaya izin verir. UIAccessibilityTraitUpdatesFrequently — sık değişen değerlere sahip öğeler için (zamanlayıcı, ilerleme göstergesi). VoiceOver her değişiklikte değeri okumaz, bir duraklama yapar. UIAccessibilityTraitAllowsDirectInteraction — kullanıcının VoiceOver hareketlerini atlayarak doğrudan etkileşime girebileceği öğeler için (klavye, çizim).
Tek bir öğe aynı anda birden çok traite sahip olabilir — kombinasyon bit düzeyinde VEYA (|) kullanılarak ayarlanır. Örnek: şu anda seçili olan bir düğme — Button | Selected. VoiceOver şunu duyuracaktır: “Seçili. Fiyata göre filtrelendi. Düğme.”
Kodda traitleri ayarlama:
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)
// Veya maske aracılığıyla:
filterButton.accessibilityTraits = [.button, .selected]
Traitin varsayılan olarak ayarlanmadığı özel UIView için:
class CustomToggle: UIControl {
override var accessibilityTraits: UIAccessibilityTraits {
get {
if isOn {
return [.button, .selected]
} else {
return .button
}
}
set {}
}
}
Birleştirme kuralı: öğe başına en fazla 3-4 trait. Aşırı traitler (örneğin, Button + Link + Header), VoiceOver duyurusunu çok uzun ve kafa karıştırıcı hale getirir. Apple'a göre, “her ek özellik kullanıcının bilişsel yükünü artırır.”
SwiftUI'de traitler, .accessibilityAddTraits() ve .accessibilityRemoveTraits() değiştiricileri kullanılarak ayarlanır. Örnek: Text(“Başlık”).font(.largeTitle).accessibilityAddTraits(.isHeader). .isHeader değiştiricisi UIAccessibilityTraitHeader ekler. SwiftUI trait listesi: .isButton, .isHeader, .isLink, .isSelected, .isImage, .isSearchField, .isKeyboardKey, .isStaticText, .isSummaryElement, .isToggle, .playsSound, .startsMediaSession, .updatesFrequently, .allowsDirectInteraction, .causesPageTurn, .isModal, .tabBar.
Button yerine StaticText — görsel olarak düğmeye benzeyen özel bir kontrol, varsayılan olarak StaticText traitini alır. VoiceOver bir etkinleştirme hareketi sunmaz, bu nedenle kullanıcı öğeye “basamaz”. Çözüm: açıkça .button ayarlayın.
Traitsiz resim — erişilebilirliği etkinleştirilmiş UIImageView, aslında fotoğrafı büyütmek için bir düğme olsa bile Image traitini alır. .button ve Label “Fotoğrafı büyüt” atayın. WWDC 2023, “Deliver an Exceptional Accessibility Experience”'e göre, yeni uygulama sürümlerindeki erişilebilirlik gerilemelerinin %40'ı trait uyuşmazlığından kaynaklanır.
Her öğede Header — Header trait'i ekranın yapısal başlıkları içindir. Her UILabel bir başlık yapılırsa, VoiceOver döner “Başlıklar” modunda işe yaramaz hale gelir — her kelimede durur.
Trait kaybının yaygın bir nedeni yeniden düzenlemedir: geliştirici, özel görüntüleme için UIButton'ı UIControl ile değiştirir. UIButton otomatik olarak Button traitini alır, UIControl almaz. Yeniden düzenlemeden sonra, açıkça accessibilityTraits = .button ayarlamanız gerekir. Kod incelemesine bir kontrol ekleyin: “UIButton'ı UIControl ile değiştirdiyseniz — traiti kontrol edin.”
Değişen duruma sahip öğeler için (örneğin, beğeni düğmesi), trait dinamik olarak değişmelidir. “Beğenilmedi” durumunda — Button, “Beğenildi” durumunda — Button + Selected + Image (simge varsa). VoiceOver duyuruyu değiştirir: “Beğen. Düğme.” vs “Seçili. Beğen. Düğme.” Selected trait yetersizse durumu iletmek için accessibilityValue kullanın. Abone düğmeleri, favoriler, filtreler ve anahtarlar için geçerlidir.
Android'de traitlerin doğrudan bir karşılığı yoktur. Bit maskesi yerine aşağıdakiler kullanılır:
Android'de özel View'ler için onInitializeAccessibilityNodeInfo geçersiz kılınmalıdır:
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 geliştiricileri, Semantics widget'ında semanticsRole parametresini kullanmalıdır: button, header, image, link, textField ve diğerleri. Ek olarak, semanticsLabel ve semanticsHint mevcuttur — iOS üçlüsü Label + Hint + Trait'in tam karşılığı.
Mobil uygulamaların web sürümleri (PWA, WebView) için WAI-ARIA'dan role niteliği kullanılır: role="button", role="heading", role="link". Bu, accessibilityTraits'in doğrudan karşılığıdır. Karma uygulamalarda, WebView'in ARIA rollerini yerel erişilebilirlik katmanına ilettiğini doğrulayın. Bunun için iOS'ta UIAccessibilityContainerDataTable protokolünü veya Android'de setAccessibilityDelegate'ı kullanın. JavaScript etkinleştirilmiş bir WebView, ARIA rollerini doğru şekilde iletmeyebilir — ayrı olarak test edin.
Android'de, AccessibilityNodeInfo'ya özel eylemler ekleyebilirsiniz: AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK ve ACTION_LONG_CLICK. Bu, ek hareketlerle Button trait'inin karşılığıdır. Kaydırıcılar için ACTION_SET_PROGRESS kullanın — Adjustable karşılığı. Spinner ve DatePicker için — ACTION_SET_SELECTION, ACTION_SET_DATE ve ACTION_SET_TIME.
Xcode Accessibility Inspector iOS için birincil araçtır: bir öğe seçin ve Traits alanını görüntüleyin. Ayarlanan traitlerin listesini gösterecektir. “Öğeler” modundaki VoiceOver döneri, ekrandaki tüm kontrollerde gezinmeyi sağlar.
Bir traiti kontrol etmek için otomatik Swift testi:
func testSubmitButtonTrait() {
let app = XCUIApplication()
app.launch()
let submitButton = app.buttons["Gönder"]
XCTAssertTrue(submitButton.isEnabled)
// XCUIElement traitlere doğrudan erişim sağlamaz
// Hareket etkinleştirme yoluyla kontrol
submitButton.tap()
XCTAssertTrue(app.staticTexts["Form gönderildi"].exists)
}
VoiceOver aracılığıyla manuel kontrol: VoiceOver'ı açın, öğeye kaydırın, çift dokunun — öğe bir Button ise etkinleşmelidir. Öğe çift dokunuşa yanıt vermezse, trait yanlıştır. Rotor hareketini kullanarak modlar arasında geçiş yapın (“Başlıklar”, “Bağlantılar”, “Düğmeler”) — her mod yalnızca ilgili traite sahip öğeleri gösterir.
iOS 14'ten önce, birim testlerinin accessibilityTraits'e doğrudan erişimi yoktu. iOS 14'ten itibaren, özellik kullanılabilir: XCTAssertEqual(customButton.accessibilityTraits, .button). Özel kontrolleri doğrulamak için birim testlerinde bunu kullanın. Özellikle yeniden düzenleme veya üst sınıf değişikliğinden sonra, her yeni özel UIView'in trait doğruluğu açısından test edilmesi önerilir.
Sıkça Sorulan Sorular
Öğe başına en fazla 3-4 trait. Daha fazla sayı, VoiceOver duyurusunu gereksiz kılar. Kombinasyonları kullanın: Button + Selected, Header + StaticText.
UIAccessibilityTraitButton. iOS, tüm UIButton örnekleri için otomatik olarak ayarlar. UIView'den miras alıp bir düğmeyi simüle ediyorsanız, trait manuel olarak ayarlanmalıdır.
Evet, UIAccessibilityTraitAdjustable — ayarlanabilir değerlere sahip öğeler için (kaydırıcılar, seçiciler, sayaçlar). VoiceOver, değeri değiştirmek ve mevcut durumu okumak için yukarı/aşağı kaydırmaya izin verir.
.accessibilityAddTraits() değiştiricisini kullanın: Text(“Başlık”).font(.title).accessibilityAddTraits(.isHeader). Yöntem iOS 14+ üzerinde çalışır.
VoiceOver None traitini atar. Öğe bir rol alamaz — ekran okuyucu, türü belirtmeden yalnızca Label'i okur. Kullanıcı, bir etkinleştirme hareketinin mevcut olup olmadığını bilemez.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun