Focus Order, arayüz öğelerinin klavye, Switch Control, VoiceOver veya TalkBack ile gezinirken odak aldığı sıradır. Mobil uygulamalarda, odak sırası kullanıcının jestler veya düğmeler aracılığıyla kontroller arasında nasıl hareket ettiğini belirler. W3C WCAG 2.2, Success Criterion 2.4.3, 2023'e göre, odak içeriğin anlamını koruyan mantıksal bir sırayı izlemelidir. Bu ilkenin ihlali, erişilebilirlik denetiminde başarısızlığın yaygın nedenlerinden biridir.
Önemli Noktalar
Focus Order, kullanıcının alternatif giriş yöntemleri (klavye (Tab), Switch Control (adım adım), VoiceOver (sağa/sola kaydırma) veya TalkBack) kullanarak etkileşimli öğeler arasında hareket etme sırasıdır. Kullanıcının doğrudan bir öğeyi seçtiği fare veya dokunmatik ekranın aksine, odak gezinmesi doğrusaldır — her adım odağı bir sonraki öğeye taşır.
Apple HIG, 2024'e göre VoiceOver, görsel yerleşime göre oluşturulan erişilebilirlik ağacındaki öğelerin sırasını kullanır: sol üst köşe → sağ alt köşe. Ekran karmaşık bir düzene (sütunlar, Grid, ZStack) sahipse, ağaç görsel sırayla eşleşmeyebilir.
WCAG 2.4.3 ilkesi: “Bir web sayfası bölümler aracılığıyla sıralı olarak gezinilebiliyorsa ve odak sırası anlamı etkiliyorsa, odak anlamı ve kullanılabilirliği koruyan bir sırayı izlemelidir”. İstisna: dikkat çekmek için odağın atlayabileceği dinamik içerik (uyarılar, modal pencereler).
Bir Switch Control kullanıcısı (motor bozukluğu olan kişiler) öğeler arasında otomatik olarak hareket eder — döngü üstüne döngü. Sıra bozulursa, kullanıcı formu tamamlamak için 3 kat daha fazla zaman harcar. Deque University, 2024'e göre, doğru Focus Order, yardımcı teknoloji kullanıcıları için form doldurma süresini %60 oranında azaltır.
Özel dikkat — modal pencereler. Bir modal açıldıktan sonra, odak modal içindeki ilk etkileşimli öğeye (genellikle “Kapat” veya “Onayla” düğmesi) hemen taşınmalıdır. Kapattıktan sonra — modalı tetikleyen öğeye geri dönmelidir. Bu, WCAG 2.4.3'ün bir gereksinimi ve aynı zamanda yaygın bir hatadır.
iOS'ta, VoiceOver geometriye dayalı olarak otomatik olarak sıra oluşturur: öğeler önce Y'ye, sonra X'e göre sıralanır. Karmaşık yapıya sahip ekranlarda bu sıra yanlış olabilir — geliştirici müdahale etmelidir.
Ana araçlar:
Ürün kartı için özel sıra ayarlama örneği:
class ProductCardView: UIView {
let titleLabel = UILabel()
let priceLabel = UILabel()
let buyButton = UIButton()
override var accessibilityElements: [Any]? {
get {
return [titleLabel!, priceLabel!, buyButton!]
}
set {}
}
}
Bir eylemden sonra programlı odak hareketi için:
UIAccessibility.post(
notification: .layoutChanged,
argument: newlyAddedItem
)
shouldGroupAccessibilityElement özelliği, koleksiyonlardaki kartlar için kullanışlıdır. Üst kartta true olarak ayarlanırsa, VoiceOver tüm kartı tek bir öğe olarak algılar. Kullanıcı, kartın tamamını etkinleştirmek için çift tıklayabilir veya iç gezinme için rotor yapılandırabilir. UICollectionViewCell ve UITableViewCell için önerilir.
Android'de, TalkBack de geometrik sırayı kullanır, ancak açık nextFocus* özniteliklerine öncelik verilir. Bu öznitelikler XML'de veya programlı olarak ayarlanır:
| Öznitelik | Amaç | Örnek |
|---|---|---|
| nextFocusDown | Aşağı gezinirken öğe | @+id/field_email |
| nextFocusUp | Yukarı gezinirken öğe | @+id/field_name |
| nextFocusLeft | Soldaki öğe | @+id/btn_back |
| nextFocusRight | Sağdaki öğe | @+id/btn_next |
Kayıt formu için örnek:
<EditText
android:id="@+id/field_email"
android:nextFocusDown="@+id/field_password" />
<EditText
android:id="@+id/field_password"
android:nextFocusDown="@+id/btn_submit" />
RecyclerView için odak sırası dinamiktir — bağdaştırıcı tarafından belirlenir. Hücreler karmaşık bir yapıya sahipse, kök öğede descendantFocusability = “beforeDescendants” ayarlayın ve liste öğesi düğümünde sırayı tanımlayın. Jetpack Compose için odak sırası Modifier.focusOrder() ve FocusOrder aracılığıyla ayarlanır. Öncelik: previous (alt), next (sonraki), özel anahtar.
Bir öğe odak için çok küçükse (44pt'den küçük), iOS'ta TouchDelegate veya Android'de minWidth/minHeight aracılığıyla vuruş alanını artırın. Google Material Design, 2024'e göre minimum dokunma alanı 48×48dp'dir. VoiceOver ve TalkBack, öğenin sınırlama kutusuna odaklanır. 30pt'den küçük öğeler jest odağı için erişilemez olabilir — kullanıcı fiziksel olarak onlara dokunamaz.
Sıçrayan odak — bir eylemden sonra (örneğin, bir öğeyi silme) odağın listenin başına veya sistem “Geri” düğmesine gitmesi. VoiceOver kullanıcısı bağlamı kaybeder. Çözüm: silinen öğeye en yakın öğeye programlı olarak odağı taşıyın.
Görünmez odak — bir öğe odak alır ancak görsel gösterge yoktur (klavye kullanıcıları nerede olduklarını göremez). iOS'ta, özel göstergeler için UIAccessibility.isVoiceOverRunning'i kontrol edin. Deque University, 2024'e göre, görünmez odak, erişilebilirlik denetiminde başarısızlığın ikinci en yaygın nedenidir.
Modaller — bir modal açıldıktan sonra odak arka plan içeriğinde kalır. iOS'ta, modalPresentationStyle = .pageSheet ayarlanmışsa modal görünümü otomatik olarak odağı yakalar. Android'de, iletişim kutusu kapsayıcısında setFocusable(true) kullanın.
Ters sorun: odak modal içinde sıkışır ve çıkış yapamaz (kapatmak dışında). Bu yalnızca modal pencereler için kabul edilebilir — kullanıcının bilinçli olarak pencereyi kapatması gerekir. Normal ekranlar için odak tuzağı kritik bir hatadır. Çözüm: modalın son öğesinin (“Kapat” düğmesi) odağı geri verdiğinden emin olun.
Özel ekranlar (haritalar, tuvaller, oyunlar) için otomatik geometrik sıra uygulanamaz. Geliştiricinin erişilebilirlik ağacını manuel olarak oluşturması gerekir. iOS'ta, bu amaçla UIAccessibilityContainer yöntemi geçersiz kılınır.
Özel tuval için örnek:
class CanvasView: UIView {
var shapes: [ShapeView] = []
override var accessibilityElements: [Any]? {
get {
// Şekilleri Z-endeksine göre sırala, geometriye göre değil
return shapes.sorted { $0.zIndex < $1.zIndex }
}
set {}
}
}
Android'de, özel bir View için onInitializeAccessibilityNodeInfo'yı geçersiz kılın:
override fun onInitializeAccessibilityNodeInfo(
info: AccessibilityNodeInfo
) {
super.onInitializeAccessibilityNodeInfo(info)
info.addChild(firstElement)
info.addChild(secondElement)
info.isFocusable = true
}
Dinamik listeler (sohbet, haber akışı) için, bir öğe ekledikten sonra odağı ilk yeni öğeye taşıyın. iOS'ta: UIAccessibility.post(notification: .layoutChanged, argument: newMessage). Android'de: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED).
iOS, öğenin çerçevesine göre otomatik olarak odak alanını belirler. Bir öğenin dönüşümü (transform, rotation) varsa, VoiceOver yanlış alana odaklanabilir. Ekran koordinatlarında açıkça accessibilityFrame ayarlayın: element.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(element.bounds, in: element). Bu, VoiceOver'ın doğru alanı vurgulamasını sağlar.
Animasyonlu ekranlar (UIKit Dynamics, Lottie, SpriteKit) için programlı odak özellikle önemlidir. VoiceOver, dinamik olarak hareket eden öğeler için bir erişilebilirlik ağacı oluşturamaz. Animasyon kaplarında isAccessibilityElement = false ve içindeki yalnızca etkileşimli öğelerde true ayarlayın.
Manuel test: VoiceOver'ı (iOS) veya TalkBack'i (Android) etkinleştirin, tüm sıra boyunca sağa kaydırın. Odak görsel sırayı izlemelidir — soldan sağa, yukarıdan aşağı. Her etkileşimli öğe tam olarak bir kez odak almalıdır.
Otomatik test zor ancak mümkündür:
func testKeyboardFocusOrder() {
let app = XCUIApplication()
app.launch()
app.textFields["Email"].tap()
// Tab — yalnızca donanım klavyesiyle
}
Android için Accessibility Testing Framework'ü kullanın:
@Test
fun testFocusOrder() {
onView(withId(R.id.fieldEmail))
.check(matches(isFocusable()))
onView(withId(R.id.fieldEmail))
.perform(focus())
onView(withId(R.id.fieldPassword))
.check(matches(isFocused()))
}
En güvenilir yöntem bir UI senaryo testidir: formu adım adım doldurun (E-posta → Şifre → Gönder), her adımın başarıyla tamamlandığını kontrol edin. Odak sırası bozulursa, senaryo odak dışı bir öğeyle etkileşim kurmaya çalışırken başarısız olur.
Xcode'daki Accessibility Inspector aracı tam erişilebilirlik ağacını gösterir. VoiceOver sırasına göre öğeler arasında gezinebilir ve tam odak yolunu görebilirsiniz. Focus Order ihlallerinin otomatik tespiti için “Audit” sekmesini kullanın.
Sıkça Sorulan Sorular
WCAG 2.4.3 (Focus Order), A düzeyi bir başarı kriteridir. Sıralı gezinme sırasında odak sırasının içerik anlamını korumasını gerektirir. İhlal kritik kabul edilir ve sertifikasyonu engeller.
Gizli öğeler, iOS'ta isAccessibilityElement = false veya Android'de visibility = gone/invisible olmalıdır. Göründüklerinde, UIAccessibility.post(notification: .layoutChanged) aracılığıyla programlı olarak odağı taşıyın.
iOS accessibilityElements ve shouldGroupAccessibilityElement aracılığıyla yönetir, Android nextFocus* öznitelikleri ve AccessibilityNodeInfo aracılığıyla. İlke aynıdır: varsayılan olarak geometrik sıra, geçersiz kılınabilir.
Kök öğede descendantFocusability = “beforeDescendants” ayarlayın ve her hücre için onInitializeAccessibilityNodeInfo aracılığıyla bağdaştırıcıda sırayı yapılandırın.
Bluetooth veya USB aracılığıyla bir donanım klavyesi bağlayın. iOS'ta odağı taşımak için Tab'a basın. Android'te TalkBack'i etkinleştirin ve Tab tuşu ile ok tuşlarını kullanın.
Ö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