Focus Order este secvența în care elementele interfeței primesc focalizarea în timpul navigării cu ajutorul tastaturii, Switch Control, VoiceOver sau TalkBack. În aplicațiile mobile, ordinea focalizării determină modul în care utilizatorul se deplasează între comenzi cu gesturi sau butoane. Conform W3C WCAG 2.2, Success Criterion 2.4.3, 2023, focalizarea trebuie să urmeze o ordine logică care păstrează sensul conținutului. Încălcarea acestui principiu este una dintre cauzele frecvente ale nepromovării auditului de accesibilitate.
Puncte cheie
Focus Order este secvența în care utilizatorul se deplasează între elementele interactive folosind metode alternative de intrare: tastatură (Tab), Switch Control (pas cu pas), VoiceOver (gest la dreapta/stânga) sau TalkBack. Spre deosebire de mouse sau ecran tactil, unde utilizatorul selectează direct un element, navigarea prin focalizare este liniară — fiecare pas mută focalizarea pe următorul element.
Conform Apple HIG, 2024, VoiceOver folosește ordinea elementelor în arborele de accesibilitate, care se construiește pe baza aranjamentului vizual: colțul stânga sus → colțul dreapta jos. Dacă ecranul conține un aspect complex (coloane, Grid, ZStack), arborele poate să nu corespundă ordinii vizuale.
Principiul WCAG 2.4.3: „Dacă o pagină web poate fi parcursă secvențial pe secțiuni și ordinea focalizării afectează sensul, atunci focalizarea trebuie să urmeze o ordine care păstrează sensul și operabilitatea”. Excepție: conținut dinamic, unde focalizarea poate sări pentru a atrage atenția (avertismente, ferestre modale).
Utilizatorul Switch Control (persoane cu deficiențe motorii) se deplasează automat prin elemente — ciclu după ciclu. Dacă ordinea este încălcată, utilizatorul pierde de 3 ori mai mult timp pentru a finaliza un formular. Conform Deque University, 2024, un Focus Order corect reduce timpul de completare a formularului cu 60% pentru utilizatorii de tehnologii asistive.
O atenție specială — ferestrelor modale. După deschiderea unei ferestre modale, focalizarea trebuie să se mute imediat pe primul element interactiv din interiorul modalei (de obicei butonul „Închide” sau „Confirmă”). După închidere — să revină la elementul care a deschis fereastra modală. Aceasta este o cerință WCAG 2.4.3 și, în același timp, o eroare frecventă.
În iOS, VoiceOver construiește automat ordinea pe baza geometriei: elementele se sortează după Y, apoi după X. Pentru ecranele cu structură complexă, această ordine poate fi incorectă — dezvoltatorul trebuie să intervină.
Instrumente principale:
Exemplu de setare a ordinii personalizate pentru o carte de produs:
class ProductCardView: UIView {
let titleLabel = UILabel()
let priceLabel = UILabel()
let buyButton = UIButton()
override var accessibilityElements: [Any]? {
get {
return [titleLabel!, priceLabel!, buyButton!]
}
set {}
}
}
Pentru mutarea programatică a focalizării după o acțiune:
UIAccessibility.post(
notification: .layoutChanged,
argument: newlyAddedItem
)
Proprietatea shouldGroupAccessibilityElement este utilă pentru cărțile din colecții. Dacă se setează true pe cartea părinte, VoiceOver percepe întreaga carte ca un singur element. Utilizatorul poate atinge de două ori pentru a activa întreaga carte sau poate configura rotorul pentru navigare în interior. Recomandat pentru UICollectionViewCell și UITableViewCell.
În Android, TalkBack folosește de asemenea ordinea geometrică, dar prioritate au atributele explicite nextFocus*. Aceste atribute se setează în XML sau programatic:
| Atribut | Destinație | Exemplu |
|---|---|---|
| nextFocusDown | Element la navigarea în jos | @+id/field_email |
| nextFocusUp | Element la navigarea în sus | @+id/field_name |
| nextFocusLeft | Elementul din stânga | @+id/btn_back |
| nextFocusRight | Elementul din dreapta | @+id/btn_next |
Exemplu pentru formularul de înregistrare:
<EditText
android:id="@+id/field_email"
android:nextFocusDown="@+id/field_password" />
<EditText
android:id="@+id/field_password"
android:nextFocusDown="@+id/btn_submit" />
Pentru RecyclerView ordinea focalizării este dinamică — este determinată de adaptor. Dacă celulele au o structură complexă, setați descendantFocusability = „beforeDescendants” și definiți ordinea în nodul elementului de listă. Pentru Jetpack Compose, ordinea focalizării se setează prin Modifier.focusOrder() și FocusOrder. Prioritate: previous (copil), next (următor), custom key.
Dacă un element este prea mic pentru focalizare (mai mic de 44 pt), măriți zona de atingere prin TouchDelegate în iOS sau minWidth/minHeight în Android. Conform Google Material Design, 2024, aria minimă de atingere este de 48×48 dp. VoiceOver și TalkBack se focalizează pe bounding box-ul elementului. Elementele mai mici de 30 pt pot fi inaccesibile pentru focalizarea prin gesturi — utilizatorul nu poate atinge fizic cu degetul.
Focalizare săritoare — când după o acțiune (de exemplu, ștergerea unui element) focalizarea se mută la începutul listei sau pe butonul de sistem „Înapoi”. Utilizatorul VoiceOver pierde contextul. Soluție: mutarea programatică a focalizării pe elementul cel mai apropiat de cel șters.
Focalizare invizibilă — elementul primește focalizare, dar nu există un indicator vizual (utilizatorii de tastatură nu văd unde se află). În iOS, verificați UIAccessibility.isVoiceOverRunning pentru indicatoare personalizate. Conform Deque University, 2024, focalizarea invizibilă este a doua cea mai frecventă cauză de eșec a auditului de accesibilitate.
Ferestre modale — focalizarea rămâne pe conținutul de fundal după deschiderea unei ferestre modale. În iOS, vizualizarea modală capturează automat focalizarea dacă este setat modalPresentationStyle = .pageSheet. În Android, utilizați setFocusable(true) pe containerul dialogului.
Problema inversă: focalizarea rămâne blocată în interiorul ferestrei modale și nu poate ieși (cu excepția închiderii). Acest lucru este permis doar pentru ferestrele modale — utilizatorul trebuie să închidă în mod conștient fereastra. Pentru ecranele obișnuite, captura de focalizare este o eroare critică. Soluție: asigurați-vă că ultimul element al ferestrei modale (butonul „Închide”) transmite focalizarea înapoi.
Pentru ecranele personalizate (hărți, pânze, jocuri), ordinea geometrică automată nu se aplică. Dezvoltatorul trebuie să construiască manual arborele de accesibilitate. În iOS, pentru aceasta se suprascrie metoda UIAccessibilityContainer.
Exemplu pentru o pânză personalizată:
class CanvasView: UIView {
var shapes: [ShapeView] = []
override var accessibilityElements: [Any]? {
get {
// Sortăm formele după indicele Z, nu după geometrie
return shapes.sorted { $0.zIndex < $1.zIndex }
}
set {}
}
}
În Android, pentru o View personalizată, suprascrieți onInitializeAccessibilityNodeInfo:
override fun onInitializeAccessibilityNodeInfo(
info: AccessibilityNodeInfo
) {
super.onInitializeAccessibilityNodeInfo(info)
info.addChild(firstElement)
info.addChild(secondElement)
info.isFocusable = true
}
Pentru listele dinamice (chat, flux de știri), după adăugarea unui element, apelați mutarea focalizării pe primul element nou. În iOS: UIAccessibility.post(notification: .layoutChanged, argument: newMessage). În Android: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED).
iOS determină automat aria de focalizare pe baza cadrului elementului. Dacă elementul are o transformare (transform, rotation), VoiceOver se poate focaliza pe o arie incorectă. Setați explicit accessibilityFrame în coordonatele ecranului: element.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(element.bounds, in: element). Aceasta garantează că VoiceOver va evidenția aria corectă.
Pentru ecranele animate (UIKit Dynamics, Lottie, SpriteKit), focalizarea programatică este deosebit de importantă. VoiceOver nu poate construi un arbore de accesibilitate pentru elementele în mișcare dinamică. Setați isAccessibilityElement = false pe containerele de animație și true doar pe elementele interactive din interior.
Testare manuală: activați VoiceOver (iOS) sau TalkBack (Android), glisați cu degetul la dreapta prin întreaga secvență. Focalizarea trebuie să urmeze ordinea vizuală — de la stânga la dreapta, de sus în jos. Fiecare element interactiv trebuie să primească focalizarea exact o dată.
Testarea automatizată este dificilă, dar posibilă:
func testKeyboardFocusOrder() {
let app = XCUIApplication()
app.launch()
app.textFields["Email"].tap()
// Tab — doar cu tastatura hardware
}
Pentru Android, utilizați Accessibility Testing Framework:
@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()))
}
Metoda cea mai fiabilă — testul de scenariu UI: completați formularul pas cu pas (Email → Parolă → Trimite), verificând că fiecare pas se finalizează cu succes. Dacă ordinea focalizării este încălcată, scenariul va eșua la încercarea de a interacționa cu un element în afara focalizării.
Instrumentul Accessibility Inspector din Xcode afișează arborele complet de accesibilitate. Puteți parcurge elementele în ordinea VoiceOver și vedea calea exactă de focalizare. Utilizați fila „Audit” pentru căutarea automată a încălcărilor Focus Order.
Întrebări frecvente
WCAG 2.4.3 (Focus Order) este un criteriu de succes de nivel A. Cere ca ordinea focalizării să păstreze sensul conținutului în timpul navigării secvențiale. Încălcarea este considerată critică și blochează certificarea.
Elementele ascunse trebuie să aibă isAccessibilityElement = false în iOS sau visibility = gone/invisible în Android. La apariție, mutați programatic focalizarea prin UIAccessibility.post(notification: .layoutChanged).
iOS gestionează prin accessibilityElements și shouldGroupAccessibilityElement, Android — prin atributele nextFocus* și AccessibilityNodeInfo. Principiul este același: ordine geometrică implicită cu posibilitate de suprascriere.
Setați descendantFocusability = „beforeDescendants” pe elementul rădăcină și configurați ordinea în adaptor prin onInitializeAccessibilityNodeInfo pentru fiecare celulă.
Conectați tastatura hardware prin Bluetooth sau USB. În iOS, apăsați Tab pentru a muta focalizarea. În Android, activați TalkBack și utilizați tastele Tab și săgețile.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și