علم الدلالات في Compose

تصف التركيبة واجهة المستخدم الخاصة بتطبيقك ويتم إنشاؤها عن طريق تشغيل العناصر القابلة للإنشاء. تتألف التركيبة من هيكل شجرة يتكوّن من العناصر القابلة للإنشاء التي تصف واجهة المستخدم.

إلى جانب المقطوعة الموسيقية، تتوفّر شجرة متوازية تُسمّى شجرة الدلالات. تصف هذه الشجرة واجهة المستخدم بطريقة بديلة مفهومة لخدمات تسهيل الاستخدام وإطار عمل الاختبار. تستخدم خدمات تسهيل الاستخدام الشجرة لوصف التطبيق للمستخدمين الذين يحتاجون إلى احتياجات محددة. يستخدم إطار عمل الاختبار الشجرة للتفاعل مع تطبيقك وتقديم تأكيدات بشأنه. لا تتضمّن شجرة دلالات الدلالات المعلومات حول كيفية رسم العناصر القابلة للإنشاء، ولكنّها تحتوي على معلومات حول المعنى الدلالي للعناصر.

العرض الهرمي النموذجي لواجهة المستخدم وشجرة دلالاته
الشكل 1. هيكل هرمي نموذجي لواجهة المستخدم وشجرة دلالاته

إذا كان تطبيقك يتألّف من عناصر قابلة للإنشاء وتعديل من مؤسسة Compose الأساسية ومكتبة المواد، يتم ملء شجرة دلالات الدلالات تلقائيًا وإنشائها نيابةً عنك. مع ذلك، عند إضافة عناصر قابلة للإنشاء مخصّصة منخفضة المستوى، عليك توفير دلالاتها يدويًا. قد تكون هناك أيضًا مواقف لا تمثل فيها شجرتك معنى العناصر الموجودة على الشاشة بشكل صحيح أو كامل، وفي هذه الحالة يمكنك تكييف الشجرة.

ضع في اعتبارك على سبيل المثال هذا التقويم المخصص القابل للإنشاء:

تقويم مخصّص قابل للإنشاء مع عناصر يوم قابلة للاختيار
الشكل 2. تقويم مخصّص قابل للإنشاء مع عناصر يوم قابلة للاختيار

في هذا المثال، يتم تنفيذ التقويم بالكامل على أنّه عنصر واحد قابل للإنشاء منخفض المستوى، باستخدام العنصر Layout القابل للإنشاء والرسم مباشرةً إلى Canvas. إذا لم تتّخذ أي إجراء آخر، لن تتلقّى خدمات تسهيل الاستخدام معلومات كافية حول محتوى العنصر القابل للإنشاء واختيار المستخدم ضمن التقويم. على سبيل المثال، إذا نقر مستخدم على اليوم الذي يبلغ 17 عامًا، لن يتلقّى إطار عمل تسهيل الاستخدام معلومات الوصف الخاصة بعنصر التحكّم في التقويم بالكامل. في هذه الحالة، ستُعلن خدمة إمكانية الوصول في TalkBack عن "التقويم" أو "تقويم نيسان (أبريل)" بشكلٍ أفضل قليلاً، وسيتساءل المستخدم عن اليوم الذي تم اختياره. لتسهيل الوصول إلى هذا العنصر القابل للإنشاء، ستحتاج إلى إضافة المعلومات الدلالية يدويًا.

خصائص المعنى

جميع العُقد في شجرة واجهة المستخدم ذات المعنى بعض الشيء لها عقدة متوازية في شجرة الدلالات. تحتوي العقدة في شجرة دلالات الدلال على تلك الخصائص التي تنقل معنى العنصر القابل للإنشاء المقابل. على سبيل المثال، تحتوي السمة Text القابلة للإنشاء على خاصية دلالية text، لأنّ هذا هو معنى ذلك العنصر. تحتوي السمة Icon على السمة contentDescription (إذا حدّدها المطوّر) تنقل معنى Icon في النص. لقد سبق أن وضعَت العناصر القابلة للإنشاء والتعديلات التي يتم إنشاؤها فوق مكتبة المؤسسات في "إنشاء" السمات ذات الصلة نيابةً عنك. اختياريًا، يمكنك ضبط السمات أو إلغاؤها بنفسك باستخدام مفتاحَي تعديل semantics وclearAndSetSemantics. على سبيل المثال، يمكنك إضافة إجراءات إمكانية الوصول المخصّصة إلى عقدة، أو توفير وصف حالة بديل لعنصر قابل للتبديل، أو الإشارة إلى أن نصًا معيّنًا قابلاً للإنشاء يجب اعتباره عنوانًا.

لعرض شجرة دلالات الدلالات، استخدِم أداة أداة فحص التنسيق أو استخدِم طريقة printToLog() ضمن الاختبارات. يؤدي هذا إلى طباعة شجرة الدلالات الحالية داخل Logcat.

class MyComposeTest {

    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun MyTest() {
        // Start the app
        composeTestRule.setContent {
            MyTheme {
                Text("Hello world!")
            }
        }
        // Log the full semantics tree
        composeTestRule.onRoot().printToLog("MY TAG")
    }
}

ستكون نتيجة هذا الاختبار على النحو التالي:

    Printing with useUnmergedTree = 'false'
    Node #1 at (l=0.0, t=63.0, r=221.0, b=120.0)px
     |-Node #2 at (l=0.0, t=63.0, r=221.0, b=120.0)px
       Text = '[Hello world!]'
       Actions = [GetTextLayoutResult]

ضع في اعتبارك كيف تنقل الخصائص الدلالية معنى العنصر القابل للإنشاء. ضع في اعتبارك Switch. هذا هو الشكل الذي يظهر للمستخدم:

الشكل 3. مفتاح تبديل بحالة "تفعيل" و "إيقاف".

لوصف معنى هذا العنصر، يمكنك قول ما يلي: "هذا مفتاح التبديل، وهو عنصر قابل للتبديل في حالته المفعَّلة". يمكنك النقر عليه للتفاعل معه".

هذا بالضبط ما يتم استخدام الخصائص الدلالية لأجله. تحتوي عقدة الدلالات لعنصر التبديل هذا على الخصائص التالية، كما هو موضح في عارض التنسيق:

أداة فحص التنسيق تعرض خصائص دلالات المحوِّل القابل للإنشاء
الشكل 4. أداة فحص التنسيق تُظهر خصائص دلالات المبدل (Switch) القابل للإنشاء

تشير السمة Role إلى نوع العنصر. وتوضّح "StateDescription" كيفية الإشارة إلى حالة "مفعَّلة". وتكون هذه النسخة مترجَمة من كلمة "مفعَّلة"، ولكن يمكن جعلها أكثر تحديدًا (على سبيل المثال، "مُفعَّلة") استنادًا إلى السياق. الوضع "ToggleableState" هو الوضع الحالي لمفتاح التحكّم. تشير السمة OnClick إلى الطريقة المستخدَمة للتفاعل مع هذا العنصر. للحصول على قائمة كاملة بسمات الدلالات، اطّلِع على الكائن SemanticsProperties. للحصول على قائمة كاملة بالإجراءات الممكنة لتسهيل الاستخدام، يُرجى الاطّلاع على العنصر SemanticsActions.

يتيح لك تتبع الخصائص الدلالية لكل عنصر قابل للإنشاء في تطبيقك الكثير من الإمكانيات القوية. في ما يلي بعض الأمثلة:

  • تستخدم ميزة Talkback الخصائص لقراءة ما يتم عرضه على الشاشة بصوت عالٍ، وتتيح للمستخدم التفاعل معه بسلاسة. بالنسبة إلى مفتاح التحكّم القابل للإنشاء، قد تظهر عبارة: "تفعيل، مفتاح تبديل، انقر مرّتين للاختيار". ويمكن للمستخدم النقر مرّتين على شاشته لإيقاف مفتاح التبديل.
  • يستخدم إطار عمل الاختبار السمات للعثور على العُقد والتفاعل معها وإجراء التأكيدات. يمكن أن يكون اختبار "مفتاح التبديل" ما يلي:
    val mySwitch = SemanticsMatcher.expectValue(
        SemanticsProperties.Role, Role.Switch
    )
    composeTestRule.onNode(mySwitch)
        .performClick()
        .assertIsOff()

شجرة دلالات الدلالات المدمَجة وغير المدمجة

كما ذكرنا سابقًا، قد لا تحتوي كل سمة قابلة للإنشاء في شجرة واجهة المستخدم على أي خاصية دلالية أو أكثر. عندما لا تتوفر خصائص دلالية في عنصر قابل للإنشاء، لا يتم تضمينه كجزء من شجرة الدلالات. بهذه الطريقة، تحتوي شجرة دلالات الدلالة فقط على العُقد التي تحتوي بالفعل على معنى دلالي. مع ذلك، لنقل المعنى الصحيح لما يظهر على الشاشة أحيانًا، من المفيد أيضًا دمج بعض الأشجار الفرعية لبعض العُقد واعتبارها واحدة. بهذه الطريقة يمكنك التفكير في مجموعة من العُقد ككل، بدلاً من التعامل مع كل عقدة تابعة على حدة. كقاعدة عامة، تمثّل كل عقدة في هذه الشجرة عنصرًا يمكن التركيز عليه عند استخدام خدمات تسهيل الاستخدام.

مثال على عنصر قابل للإنشاء: Button. يمكنك التفكير في الزر كعنصر واحد، على الرغم من أنه قد يحتوي على العديد من العُقد الفرعية:

Button(onClick = { /*TODO*/ }) {
    Icon(
        imageVector = Icons.Filled.Favorite,
        contentDescription = null
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}

في شجرة دلالات الدلالات، يتم دمج خصائص توابع الزر، ويتم تقديم الزر كعقدة ورقة واحدة في الشجرة:

تم دمج تمثيل دلالي ذي ورقة واحدة.
الشكل 5. تم دمج تمثيل دلالي ذي ورقة واحدة.

يمكن أن تشير العناصر القابلة للإنشاء والتعديل إلى أنّها تريد دمج سمات دلالات العناصر التابعة من خلال طلب Modifier.semantics (mergeDescendants = true) {}. أمّا ضبط هذه السمة على true، فيشير إلى أنّه يجب دمج السمات الدلالية. في مثال Button، تستخدم العنصر Button القابل للإنشاء المعدِّل clickable داخليًا الذي يتضمّن مفتاح التعديل semantics هذا. وبالتالي، يتم دمج العُقد التابعة للزر. اطّلِع على مستندات تسهيل الاستخدام لمعرفة المزيد من المعلومات حول الحالات التي يجب فيها تغيير سلوك الدمج في العنصر القابل للإنشاء.

ويتم تعيين هذه الخصائص للعديد من المعدِّلات والعناصر القابلة للإنشاء في مكتبات Foundation وMaterial Compose. على سبيل المثال، سيتم دمج عناصر تعديل clickable وtoggleable تلقائيًا. وستدمج عناصر ListItem القابلة للإنشاء العناصر التابعة له.

افحص الأشجار

شجرة الدلالات هي في الحقيقة شجرتان مختلفتان. تتوفّر شجرة دلالات مدمجة تدمج العُقد التابعة عند ضبط mergeDescendants على true. هناك أيضًا شجرة دلالات غير مدمجة، لا تنطبق على الدمج ولكنها تحافظ على كل عُقدة سليمة. تستخدم خدمات تسهيل الاستخدام الشجرة غير المدمَجة وتطبِّق خوارزميات الدمج الخاصة بها، مع مراعاة السمة mergeDescendants. يستخدم إطار عمل الاختبار الشجرة المدمجة افتراضيًا.

ويمكنك فحص كلتا الشجرتَين باستخدام طريقة printToLog(). بشكل افتراضي، وكما في الأمثلة السابقة، يتم تسجيل الشجرة المدمجة. لطباعة الشجرة غير المدمَجة بدلاً من ذلك، اضبط المعلَمة useUnmergedTree لمطابق onRoot() على true:

composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")

تتيح لك أداة فحص التنسيق عرض كل من شجرة دلالات الدلالات المدمجة وغير المدمجة، عن طريق تحديد شجرة العرض المفضلة في عامل تصفية العرض:

خيارات عرض أداة فحص التنسيق، التي تسمح بعرض شجرة دلالات الدلالات المدمجة وغير المدمجة
الشكل 6. خيارات عرض أداة فحص التنسيق، التي تسمح بعرض شجرة دلالات الدلالات المدمجة وغير المدمجة.

لكل عقدة في شجرتك، يعرض عارض التنسيق كلاً من دلالات الدلالات المدمَجة ودلالة الدلالات التي تم تعيينها في تلك العقدة في لوحة الخصائص:

تم دمج الخصائص الدلالية وضبطها.
الشكل 7. تم دمج الخصائص الدلالية وإعدادها.

بشكل تلقائي، تستخدم أدوات المطابقة في "إطار عمل الاختبار" شجرة دلالات الدلالات المدمجة. لهذا السبب يمكنك التفاعل مع Button من خلال مطابقة النص المعروض بداخلها:

composeTestRule.onNodeWithText("Like").performClick()

يمكنك إلغاء هذا السلوك من خلال ضبط معلَمة useUnmergedTree الخاصة بمطابقة العبارات على true، كما هو الحال في مُطابق onRoot.

سلوك الدمج

عندما يشير عنصر قابل للإنشاء إلى أنّه يجب دمج العناصر التابعة له، كيف يحدث هذا الدمج بالضبط؟

لكل سمة دلالية استراتيجية دمج محدّدة. على سبيل المثال، تضيف السمة ContentDescription جميع قيم ContentDescription التابعة إلى قائمة. يمكنك التحقّق من استراتيجية دمج سمة دلالية من خلال التحقّق من تنفيذ mergePolicy الخاصة بها في SemanticsProperties.kt. يمكن أن تأخذ الخصائص القيمة الرئيسية أو الفرعية، أو تدمج القيم في قائمة أو سلسلة، أو لا تسمح بالدمج على الإطلاق، وتعرض استثناءً بدلاً من ذلك، أو أي استراتيجية دمج مخصّصة أخرى.

وتجدر الإشارة إلى أنّ العناصر التابعة التي ضبطت mergeDescendants = true لا يتم تضمينها في عملية الدمج. ألقِ نظرة على مثال:

عنصر قائمة مع صورة وبعض النصوص ورمز إشارة مرجعية
الشكل 8. عنصر قائمة مع صورة وبعض النصوص ورمز إشارة مرجعية

إليك عنصر قائمة قابل للنقر. عندما يضغط المستخدم على الصف، ينتقل التطبيق إلى صفحة تفاصيل المقالة، حيث يمكن للمستخدم قراءة المقالة. يوجد داخل عنصر القائمة زر لوضع إشارة مرجعية على المقالة، مما يشكل عنصرًا مدمجًا قابلاً للنقر، بحيث يظهر الزر بشكل منفصل في الشجرة المدمجة. يتم دمج باقي المحتوى في الصف:

تحتوي الشجرة المدمجة على نصوص متعددة في قائمة داخل عقدة الصف. تحتوي الشجرة التي لم يتم دمجها على عُقد منفصلة لكل نص قابل للإنشاء.
الشكل 9. تحتوي الشجرة المدمجة على نصوص متعددة في قائمة داخل عقدة الصف. تحتوي الشجرة غير المدمجة على عُقد منفصلة لكل نص قابل للإنشاء.

تكييف شجرة الدلالة

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

مراجع إضافية