Focus Order — ما هو، مبادئه وكيفية إعداده في التطبيقات المحمولة

المؤلف: IT Sectr نُشر: 2026-05-16 وقت القراءة: 9 دق

Focus Order هو التسلسل الذي تستقبل فيه عناصر الواجهة التركيز عند التنقل باستخدام لوحة المفاتيح أو Switch Control أو VoiceOver أو TalkBack. في التطبيقات المحمولة، يحدد ترتيب التركيز كيفية تنقل المستخدم بين عناصر التحكم باستخدام الإيماءات أو الأزرار. وفقًا لـ W3C WCAG 2.2, Success Criterion 2.4.3, 2023، يجب أن يتبع التركيز ترتيبًا منطقيًا يحافظ على معنى المحتوى. يُعد انتهاك هذا المبدأ أحد الأسباب الشائعة لفشل تدقيق إمكانية الوصول.

الوجبات الرئيسية

  • Focus Order — تسلسل اجتياز العناصر التفاعلية عند التنقل باستخدام لوحة المفاتيح أو قارئ الشاشة
  • يجب أن يتبع التركيز الترتيب البصري (من اليسار إلى اليمين، من الأعلى إلى الأسفل) ويحافظ على منطق المحتوى
  • في iOS، يتم ضبط الترتيب عبر shouldGroupAccessibilityElement ومصفوفة accessibilityElements
  • في Android، تحدد السمات nextFocusDown و nextFocusUp و nextFocusLeft و nextFocusRight جيران التركيز
  • تتطلب الشاشات المخصصة (الخرائط، اللوحات، الألعاب) إدارة برمجية للتركيز عبر UIAccessibilityPostNotification

ما هو Focus Order في إمكانية الوصول

Focus Order هو التسلسل الذي يتنقل فيه المستخدم بين العناصر التفاعلية باستخدام طرق الإدخال البديلة: لوحة المفاتيح (Tab)، Switch Control (خطوة بخطوة)، VoiceOver (التمرير لليمين/اليسار) أو TalkBack. على عكس الماوس أو الشاشة التي تعمل باللمس، حيث يختار المستخدم العنصر مباشرة، فإن التنقل بالتركيز خطي — كل خطوة تنقل التركيز إلى العنصر التالي.

وفقًا لـ Apple HIG, 2024، يستخدم VoiceOver ترتيب العناصر في شجرة إمكانية الوصول، والتي تُبنى بناءً على الموضع البصري: الزاوية العلوية اليسرى → الزاوية السفلية اليمنى. إذا كانت الشاشة تحتوي على تخطيط معقد (أعمدة، Grid، ZStack)، فقد لا تتطابق الشجرة مع الترتيب البصري.

مبدأ WCAG 2.4.3: «إذا كان من الممكن التنقل في صفحة الويب بالتسلسل عبر الأقسام وكان ترتيب التركيز يؤثر على المعنى، فيجب أن يتبع التركيز ترتيبًا يحافظ على المعنى وإمكانية التشغيل». الاستثناء: المحتوى الديناميكي حيث يمكن للتركيز القفز لجذب الانتباه (التنبيهات، النوافذ المشروطة).

لماذا Focus Order مهم لإمكانية الوصول

مستخدم Switch Control (الأشخاص ذوو الإعاقات الحركية) يتنقل بين العناصر تلقائيًا — دورة بعد دورة. إذا كان الترتيب مكسورًا، يستغرق المستخدم 3 أضعاف الوقت لإكمال النموذج. وفقًا لـ Deque University, 2024، يقلل Focus Order الصحيح من وقت إكمال النموذج بنسبة 60% لمستخدمي التقنيات المساعدة.

Focus Order والنوافذ المشروطة

اهتمام خاص — النوافذ المشروطة. بعد فتح نافذة مشروطة، يجب أن ينتقل التركيز فورًا إلى أول عنصر تفاعلي داخل النافذة (عادةً زر «إغلاق» أو «تأكيد»). بعد الإغلاق — العودة إلى العنصر الذي استدعى النافذة. هذا مطلب من WCAG 2.4.3 وأيضًا خطأ شائع.

iOS: إدارة ترتيب التركيز

في iOS، يقوم VoiceOver تلقائيًا ببناء الترتيب بناءً على الهندسة: يتم فرز العناصر حسب Y، ثم حسب X. للشاشات ذات البنية المعقدة، قد يكون هذا الترتيب غير صحيح — يجب على المطور التدخل.

الأدوات الرئيسية:

  • shouldGroupAccessibilityElement — يجمع العناصر الفرعية في كتلة منطقية واحدة
  • accessibilityElements — مصفوفة تحدد الترتيب المخصص للعناصر الفرعية
  • UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, element) — النقل البرمجي للتركيز

مثال لتعيين ترتيب مخصص لبطاقة منتج:

swift
class ProductCardView: UIView {
    let titleLabel = UILabel()
    let priceLabel = UILabel()
    let buyButton = UIButton()

    override var accessibilityElements: [Any]? {
        get {
            return [titleLabel!, priceLabel!, buyButton!]
        }
        set {}
    }
}

للنقل البرمجي للتركيز بعد إجراء:

swift
UIAccessibility.post(
    notification: .layoutChanged,
    argument: newlyAddedItem
)

shouldGroupAccessibilityElement في الممارسة

خاصية shouldGroupAccessibilityElement مفيدة للبطاقات في المجموعات. إذا تم تعيينها على true في البطاقة الأصلية، يدرك VoiceOver البطاقة بأكملها كعنصر واحد. يمكن للمستخدم النقر مرتين لتنشيط البطاقة بأكملها، أو تكوين القرص الدوار للتنقل الداخلي. موصى به لـ UICollectionViewCell و UITableViewCell.

Android: سمات اتجاه التركيز

في Android، يستخدم TalkBack أيضًا الترتيب الهندسي، ولكن تُعطى الأولوية للسمات الصريحة nextFocus*. يتم تعيين هذه السمات في XML أو برمجيًا:

السمةالغرضمثال
nextFocusDownالعنصر عند التنقل لأسفل@+id/field_email
nextFocusUpالعنصر عند التنقل لأعلى@+id/field_name
nextFocusLeftالعنصر إلى اليسار@+id/btn_back
nextFocusRightالعنصر إلى اليمين@+id/btn_next

مثال لنموذج تسجيل:

xml
<EditText
    android:id="@+id/field_email"
    android:nextFocusDown="@+id/field_password" />

<EditText
    android:id="@+id/field_password"
    android:nextFocusDown="@+id/btn_submit" />

بالنسبة لـ RecyclerView، ترتيب التركيز ديناميكي — يحدده المحول. إذا كانت الخلايا ذات بنية معقدة، فقم بتعيين descendantFocusability = «beforeDescendants» وحدد الترتيب في عقدة عنصر القائمة. بالنسبة لـ Jetpack Compose، يتم تعيين ترتيب التركيز عبر Modifier.focusOrder() و FocusOrder. الأولوية: previous (فرعي)، next (تالي)، مفتاح مخصص.

TouchDelegate ومنطقة اللمس ومنطقة التركيز

إذا كان العنصر صغيرًا جدًا بالنسبة للتركيز (أقل من 44pt)، فقم بزيادة منطقة اللمس عبر TouchDelegate في iOS أو minWidth/minHeight في Android. وفقًا لـ Google Material Design, 2024، الحد الأدنى لمنطقة اللمس هو 48×48dp. يركز VoiceOver و TalkBack على المربع المحيط للعنصر. قد لا يمكن الوصول إلى العناصر الأصغر من 30pt للتركيز بالإيماءات — لا يمكن للمستخدم لمسها فعليًا.

الانتهاكات الشائعة لـ WCAG 2.4.3

التركيز القافز — عندما ينتقل التركيز بعد إجراء (مثل حذف عنصر) إلى بداية القائمة أو إلى زر «رجوع» النظامي. يفقد مستخدم VoiceOver السياق. الحل: نقل التركيز برمجيًا إلى العنصر الأقرب للعنصر المحذوف.

التركيز غير المرئي — يتلقى العنصر تركيزًا ولكن لا يوجد مؤشر مرئي (لا يرى مستخدمو لوحة المفاتيح مكانهم). في iOS، تحقق من UIAccessibility.isVoiceOverRunning للمؤشرات المخصصة. وفقًا لـ Deque University, 2024، التركيز غير المرئي هو ثاني أكثر سبب شيوعًا لفشل تدقيق إمكانية الوصول.

النوافذ المشروطة — يظل التركيز على المحتوى الخلفي بعد فتح نافذة مشروطة. في iOS، تلتقط النافذة المشروطة التركيز تلقائيًا إذا تم تعيين modalPresentationStyle = .pageSheet. في Android، استخدم setFocusable(true) على حاوية الحوار.

مصيدة التركيز

المشكلة العكسية: يعلق التركيز داخل النافذة المشروطة ولا يمكنه الخروج (باستثناء الإغلاق). هذا مقبول فقط للنوافذ المشروطة — يجب على المستخدم إغلاق النافذة عن قصد. للشاشات العادية، مصيدة التركيز خطأ فادح. الحل: تأكد من أن العنصر الأخير في النافذة المشروطة (زر «إغلاق») يعيد التركيز.

الشاشات المخصصة والتركيز البرمجي

بالنسبة لـ الشاشات المخصصة (الخرائط، اللوحات، الألعاب) لا ينطبق الترتيب الهندسي التلقائي. يجب على المطور بناء شجرة إمكانية الوصول يدويًا. في iOS، يتم تجاوز طريقة UIAccessibilityContainer لهذا الغرض.

مثال للوحة مخصصة:

swift
class CanvasView: UIView {
    var shapes: [ShapeView] = []

    override var accessibilityElements: [Any]? {
        get {
            // فرز الأشكال حسب مؤشر Z، وليس حسب الهندسة
            return shapes.sorted { $0.zIndex < $1.zIndex }
        }
        set {}
    }
}

في Android، لعرض مخصص، تجاوز onInitializeAccessibilityNodeInfo:

kotlin
override fun onInitializeAccessibilityNodeInfo(
    info: AccessibilityNodeInfo
) {
    super.onInitializeAccessibilityNodeInfo(info)
    info.addChild(firstElement)
    info.addChild(secondElement)
    info.isFocusable = true
}

بالنسبة لـ القوائم الديناميكية (الدردشة، خلاصة الأخبار)، بعد إضافة عنصر، انقل التركيز إلى أول عنصر جديد. في iOS: UIAccessibility.post(notification: .layoutChanged, argument: newMessage). في Android: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED).

AccessibilityFrame وهندسة التركيز

يحدد iOS تلقائيًا منطقة التركيز بناءً على إطار العنصر. إذا كان للعنصر تحويل (transform, rotation)، فقد يركز VoiceOver على المنطقة الخطأ. قم بتعيين accessibilityFrame صراحةً في إحداثيات الشاشة: element.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(element.bounds, in: element). هذا يضمن أن VoiceOver يسلط الضوء على المنطقة الصحيحة.

UIKit Dynamics وإمكانية الوصول

للشاشات المتحركة (UIKit Dynamics, Lottie, SpriteKit)، التركيز البرمجي مهم بشكل خاص. لا يمكن لـ VoiceOver بناء شجرة إمكانية وصول للعناصر المتحركة ديناميكيًا. قم بتعيين isAccessibilityElement = false على حاويات الرسوم المتحركة و true فقط على العناصر التفاعلية داخلها.

اختبار ترتيب التركيز

الاختبار اليدوي: قم بتشغيل VoiceOver (iOS) أو TalkBack (Android)، مرر لليمين عبر التسلسل بأكمله. يجب أن يتبع التركيز الترتيب البصري — من اليسار إلى اليمين، من الأعلى إلى الأسفل. يجب أن يتلقى كل عنصر تفاعلي التركيز مرة واحدة بالضبط.

الاختبار الآلي صعب ولكنه ممكن:

swift
func testKeyboardFocusOrder() {
    let app = XCUIApplication()
    app.launch()
    app.textFields["Email"].tap()
    // Tab — فقط مع لوحة المفاتيح الفعلية
}

بالنسبة لـ Android، استخدم Accessibility Testing Framework:

kotlin
@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()))
}

الطريقة الأكثر موثوقية هي اختبار سيناريو واجهة المستخدم: املأ النموذج خطوة بخطوة (البريد الإلكتروني → كلمة المرور → إرسال)، للتحقق من اكتمال كل خطوة بنجاح. إذا كان ترتيب التركيز مكسورًا، سيفشل السيناريو عند محاولة التفاعل مع عنصر خارج التركيز.

Xcode Accessibility Inspector للتصحيح

أداة Accessibility Inspector في Xcode تعرض شجرة إمكانية الوصول الكاملة. يمكنك التنقل عبر العناصر بترتيب VoiceOver ورؤية مسار التركيز الدقيق. استخدم علامة التبويب «Audit» للكشف التلقائي عن انتهاكات Focus Order.

الأسئلة الشائعة

ما هو WCAG 2.4.3 وما هي متطلبات التركيز؟

WCAG 2.4.3 (Focus Order) هو معيار نجاح من المستوى A. يتطلب أن يحافظ ترتيب التركيز على معنى المحتوى أثناء التنقل المتسلسل. يعتبر الانتهاك خطيرًا ويمنع الاعتماد.

كيفية تعيين ترتيب التركيز للعناصر المخفية خلف الرسوم المتحركة؟

يجب أن تحتوي العناصر المخفية على isAccessibilityElement = false في iOS أو visibility = gone/invisible في Android. عند ظهورها، انقل التركيز برمجيًا عبر UIAccessibility.post(notification: .layoutChanged).

ما الفرق بين التركيز في iOS و Android؟

iOS يدير عبر accessibilityElements و shouldGroupAccessibilityElement، Android عبر سمات nextFocus* و AccessibilityNodeInfo. المبدأ واحد: ترتيب هندسي افتراضي مع إمكانية التجاوز.

ماذا أفعل إذا كان RecyclerView بترتيب خاطئ؟

قم بتعيين descendantFocusability = «beforeDescendants» على العنصر الجذر واضبط الترتيب في المحول عبر onInitializeAccessibilityNodeInfo لكل خلية.

كيفية اختبار التركيز بدون VoiceOver؟

قم بتوصيل لوحة مفاتيح فعلية عبر Bluetooth أو USB. في iOS اضغط Tab لتحريك التركيز. في Android قم بتشغيل TalkBack واستخدم مفتاح Tab ومفاتيح الأسهم.

الملخص

  • Focus Order — تسلسل اجتياز العناصر عند التنقل باستخدام لوحة المفاتيح أو قارئ الشاشة؛ مبني على WCAG 2.4.3
  • يجب أن يتبع التركيز الترتيب البصري (من اليسار إلى اليمين، من الأعلى إلى الأسفل) — تلقائيًا في VoiceOver و TalkBack
  • في iOS، يتم ضبط الترتيب عبر accessibilityElements و shouldGroupAccessibilityElement
  • في Android تُستخدم السمات nextFocusDown و nextFocusUp و nextFocusLeft و nextFocusRight
  • تتطلب الشاشات المخصصة (الخرائط، اللوحات) إدارة برمجية للتركيز عبر UIAccessibilityPostNotification
  • انتهاك الترتيب هو خطأ فادح في WCAG 2.4.3؛ يفقد المستخدمون السياق ولا يمكنهم إكمال السيناريو
  • اختبر التركيز عبر إيماءات VoiceOver/TalkBack ولوحة المفاتيح الفعلية و السيناريوهات الآلية

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا