بالإضافة إلى المعلومات الأساسية التي يحملها العنصر القابل للتجميع، مثل سلسلة نصية
لعنصر قابل للتجميع من النوع Text
، قد يكون من المفيد الحصول على المزيد من المعلومات
الإضافية عن عناصر واجهة المستخدم.
تُعرف المعلومات عن معنى المكوّن ودوره في Compose باسم الدلالات، وهي طريقة لتقديم سياق إضافي عن العناصر القابلة للإنشاء لخدمات مثل تسهيل الاستخدام والملء التلقائي والاختبار. على سبيل المثال، قد يكون رمز الكامير مجرد صورة، ولكن قد يكون المعنى الدلالي هو "التقاط صورة".
من خلال الجمع بين الدلالات المناسبة وواجهات برمجة تطبيقات Compose المناسبة، يمكنك تقديم أكبر قدر ممكن من المعلومات عن المكوّن إلى خدمات تسهيل الاستخدام، والتي تحدّد بعد ذلك كيفية تمثيله للمستخدم.
تأتي واجهات برمجة التطبيقات Material وCompose UI وFoundation API مع دلالات مضمّنة تتبع دورها ووظيفتها المحدّدة، ولكن يمكنك أيضًا تعديل هذه الدلالة لواجهات برمجة التطبيقات الحالية أو ضبط دلالات جديدة للمكوّنات المخصّصة وفقًا ل requirements الخاصة بك.
الخصائص الدلالية
تنقل السمات الدلالية معنى العنصر القابل للتجميع المقابل. على سبيل المثال، يحتوي العنصر القابل للتجميع Text
على خاصيّة دلالية text
، لأنّه يمثّل معنى هذا العنصر القابل للتجميع. يحتوي الرمز Icon
على سمة
contentDescription
(إذا ضبطها المطوّر) تنقل في نص
معنى الرمز.
فكِّر في كيفية نقل خصائص الدلالة معنى العنصر القابل للتجميع. ننصحك باستخدام
Switch
. إليك كيفية ظهور ذلك للمستخدم:

Switch
في حالتَي "مفعَّل" و "غير مفعَّل"لوصف معنى هذا العنصر، يمكنك قول ما يلي: "هذا مفتاح تبديل، وهو عنصر يمكن التبديل بين حالته "مشغّل" و"غير مفعّل". يمكنك النقر عليه للتفاعل معه".
وهذا هو الغرض بالضبط من استخدام سمات الدلالات. تحتوي عقدة الدلالات لعنصر Switch هذا على السمات التالية، كما هو موضّح باستخدام أداة Layout Inspector:

Switch
للمحتوى القابل للإنشاءيشير الرمز Role
إلى نوع العنصر. يصف StateDescription
كيفية
الإشارة إلى الحالة "مفعّل". يكون هذا العنصر تلقائيًا نسخة مترجَمة من
الكلمة "تفعيل"، ولكن يمكن أن يكون أكثر تحديدًا (على سبيل المثال، "مفعَّل") استنادًا
إلى السياق. يشير الرمز ToggleableState
إلى الحالة الحالية لجهاز التحكّم. تشير السمة
OnClick
إلى الطريقة المستخدَمة للتفاعل مع هذا العنصر.
من خلال تتبُّع سمات الدلالات لكل عنصر قابل للتجميع في تطبيقك، يمكنك الاستفادة من العديد من الإمكانات الفعّالة:
- تستخدِم خدمات تسهيل الاستخدام السمات لتمثيل واجهة المستخدم المعروضة على الشاشة، والسماح للمستخدمين بالتفاعل معها. بالنسبة إلى عنصر التبديل القابل للتجميع، قد يُعلِن تطبيق TalkBack عن: "مفعَّل، مفتاح تبديل، انقر مرّتين للتبديل". يمكن للمستخدم النقر مرّتين على الشاشة لإيقاف التبديل.
-
يستخدم إطار عمل الاختبار الخصائص للعثور على العقد والتفاعل
معها وإجراء التأكيدات:
val mySwitch = SemanticsMatcher.expectValue( SemanticsProperties.Role, Role.Switch ) composeTestRule.onNode(mySwitch) .performClick() .assertIsOff()
إنّ العناصر القابلة للتجميع والمُعدِّلات التي تم إنشاؤها استنادًا إلى مكتبة Compose الأساسية قد سبق أن ضبطت الخصائص ذات الصلة تلقائيًا نيابةً عنك. يمكنك اختياريًا تغيير هذه السمات يدويًا لتحسين تسهيل الاستخدام في حالات استخدام معيّنة، أو تغيير استراتيجية دمج أو محو العناصر القابلة للتجميع.
للإشارة إلى نوع المحتوى المحدّد لمكوّنك إلى خدمات تسهيل الاستخدام، يمكنك تطبيق مجموعة متنوعة من المعاني المختلفة. ستوفّر هذه الإضافات المعلومات الدلالية الرئيسية الحالية وستساعد خدمات تسهيل الاستخدام في تحسين طريقة عرض المكوّن أو الإعلان عنه أو التفاعل معه.
للحصول على قائمة كاملة بسمات الدلالات، اطّلِع على عنصر
SemanticsProperties
. للحصول على قائمة كاملة بإجراءات Accessibility
المحتمَلة، اطّلِع على العنصر SemanticsActions
.
العناوين
غالبًا ما تحتوي التطبيقات على شاشات تتضمّن محتوى نصيًا كثيفًا، مثل المقالات الطويلة أو صفحات الأخبار، والتي تنقسم عادةً إلى أقسام فرعية مختلفة تتضمّن عناوين:

قد يواجه المستخدمون الذين يحتاجون إلى تسهيل الاستخدام صعوبة في التنقّل في هذه الشاشة
بسهولة. لتحسين تجربة التنقّل، تتيح بعض خدمات تسهيل الاستخدام
لتسهيل التنقّل مباشرةً بين الأقسام أو العناوين. لتفعيل هذه الميزة،
حدِّد أنّ المكوّن هو heading
من خلال تحديد سمة
دلالية:
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
التنبيهات والنوافذ المنبثقة
إذا كان المكوّن عبارة عن تنبيه أو نافذة منبثقة، مثل Snackbar
، قد تحتاج إلى إعلام خدمات تسهيل الاستخدام بأنّه يمكن إرسال بنية جديدة أو تعديلات على المحتوى إلى المستخدمين.
يمكن وضع علامة على المكوّنات التي تشبه التنبيهات باستخدام سمة liveRegion
semantics. يتيح ذلك لخدمات تسهيل الاستخدام إعلام المستخدم تلقائيًا بالتغيُّرات التي تطرأ على هذا المكوّن أو عناصره الفرعية:
PopupAlert( message = "You have a new message", modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite } )
يجب استخدام liveRegionMode.Polite
في معظم الحالات التي يجب فيها جذب انتباه المستخدمين
لوقت قصير فقط إلى التنبيهات أو المحتوى المتغيّر المهم على الشاشة.
يجب استخدام liveRegion.Assertive
بشكل مقتصد لتجنّب تقديم ملاحظات مزعجة.
يجب استخدامها في الحالات التي يكون فيها من الضروري إعلام المستخدمين
بالمحتوى المرتبط بوقت محدّد:
PopupAlert( message = "Emergency alert incoming", modifier = Modifier.semantics { liveRegion = LiveRegionMode.Assertive } )
يجب عدم استخدام المناطق النشطة في المحتوى الذي يتم تعديله بشكل متكرّر، مثل الموقّتات التنازلية، لتجنّب إرباك المستخدمين من خلال تقديم ملاحظات مستمرة.
المكونات الشبيهة بالنوافذ
إنّ المكوّنات المخصّصة التي تشبه النوافذ، مثل ModalBottomSheet
، تحتاج إلى إشارات إضافية
لتمييزها عن المحتوى المحيط بها. ولإجراء ذلك، يمكنك استخدام سمات
paneTitle
، لكي تتمكّن خدمات تسهيل الاستخدام من
تمثيل أي تغييرات ذات صلة بالنافذة أو اللوحة بشكلٍ مناسب، إلى جانب
معلوماتها الدلالية الرئيسية:
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
للاطّلاع على مزيد من المعلومات، يمكنك الاطّلاع على كيفية استخدام Material 3 لنظام paneTitle
في مكوّناته.
مكوّنات الخطأ
بالنسبة إلى أنواع المحتوى الأخرى، مثل المكونات التي تشبه الأخطاء، ننصحك بمحاولة
توسيع نطاق المعلومات الدلالية الرئيسية للمستخدمين الذين لديهم احتياجات خاصة بإمكانية الاستخدام.
عند تحديد حالات الخطأ، يمكنك إبلاغ خدمات تسهيل الاستخدام بدلالتها
error
وتقديم رسائل خطأ موسّعة.
في هذا المثال، يقرأ تطبيق TalkBack معلومات نص الخطأ الرئيسية، يليها رسائل إضافية ومفصّلة:
Error( errorText = "Fields cannot be empty", modifier = Modifier .semantics { error("Please add both email and password") } )
مكوّنات تتبُّع مستوى التقدّم
بالنسبة إلى المكوّنات المخصّصة التي تتتبّع مستوى التقدّم، قد تحتاج إلى إبلاغ المستخدمين بتغيُّرات مستوى التقدّم، بما في ذلك قيمة مستوى التقدّم الحالي ونطاقه ومقدار الخطوة. يمكنك إجراء ذلك باستخدام دلالات progressBarRangeInfo
، ما يضمن أن تكون خدمات تسهيل الاستخدام على دراية بتغييرات مستوى التقدّم، ويمكنها إعلام المستخدمين وفقًا لذلك. قد تتضمّن أيضًا التكنولوجيات المساعِدة المختلفة
طُرقًا فريدة للإشارة إلى زيادة التقدّم أو انخفاضه.
ProgressInfoBar( modifier = Modifier .semantics { progressBarRangeInfo = ProgressBarRangeInfo( current = progress, range = 0F..1F ) } )
معلومات القائمة والعناصر
في القوائم والمشابك المخصّصة التي تحتوي على العديد من العناصر، قد يكون من المفيد لخدمات تسهيل الاستخدامتلقّي معلومات أكثر تفصيلاً أيضًا، مثل إجمالي عدد العناصر والمؤشرات.
باستخدام الدلالات collectionInfo
وcollectionItemInfo
في
القائمة والعناصر على التوالي، يمكن لخدمات تسهيل الاستخدام إعلام المستخدمين في هذه القائمة الطويلة
بفهرس العنصر الذي وصلوا إليه من إجمالي المجموعة، بالإضافة إلى
المعلومات الدلالية النصية:
MilkyWayList( modifier = Modifier .semantics { collectionInfo = CollectionInfo( rowCount = milkyWay.count(), columnCount = 1 ) } ) { milkyWay.forEachIndexed { index, text -> Text( text = text, modifier = Modifier.semantics { collectionItemInfo = CollectionItemInfo(index, 0, 0, 0) } ) } }
وصف الحالة
يمكن للعنصر القابل للإنشاء تحديد stateDescription
للدلالات التي يستخدمها
إطار عمل Android لقراءة الحالة التي يكون عليها العنصر القابل للإنشاء. على سبيل المثال، يمكن أن يكون العنصر القابل للتبديل في حالة "محدَّد" أو "غير محدَّد". في بعض الحالات، قد تحتاج إلى إلغاء وصف الحالة الافتراضية
للتصنيفات التي تستخدمها ميزة "الإنشاء". يمكنك إجراء ذلك من خلال تحديد تصنيفات وصف الحالة بوضوح قبل تحديد عنصر قابل للتبديل على أنّه عنصر قابل للتجميع:
@Composable private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) { val stateSubscribed = stringResource(R.string.subscribed) val stateNotSubscribed = stringResource(R.string.not_subscribed) Row( modifier = Modifier .semantics { // Set any explicit semantic properties stateDescription = if (selected) stateSubscribed else stateNotSubscribed } .toggleable( value = selected, onValueChange = { onToggle() } ) ) { /* ... */ } }
الإجراءات المخصّصة
يمكن استخدام الإجراءات المخصّصة للإيماءات الأكثر تعقيدًا على شاشة اللمس، مثل المسح السريع لإغلاق العنصر أو السحب والإفلات، لأنّ هذه الإجراءات قد تكون صعبة على المستخدمين الذين يعانون من عجز في المهارات الحركية أو عجز آخر.
لتسهيل استخدام إيماءة التمرير السريع لإغلاق التطبيق، يمكنك ربطها بأحد الإجراءات المخصّصة، مع تمرير إجراء الإغلاق والتصنيف إليها:
SwipeToDismissBox( modifier = Modifier.semantics { // Represents the swipe to dismiss for accessibility customActions = listOf( CustomAccessibilityAction( label = "Remove article from list", action = { removeArticle() true } ) ) }, state = rememberSwipeToDismissBoxState(), backgroundContent = {} ) { ArticleListItem() }
بعد ذلك، تُبرز خدمة تسهيل الاستخدام، مثل TalkBack، المكوّن وتشير إلى أنّه يتوفّر المزيد من الإجراءات في قائمتها، ما يمثّل التمرير سريعًا لإغلاق الإجراء:

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

لتحسين تجربة التنقّل، وهو أمر مفيد بشكل خاص لتكنولوجيات المساعدة المستندة إلى التفاعل، مثل "الوصول عبر مفتاح التحكّم" أو Voice Access، يمكنك استخدام إجراءات مخصّصة في الحاوية لنقل الإجراءات من التنقّل الفردي إلى قائمة إجراءات منفصلة:
ArticleListItemRow( modifier = Modifier .semantics { customActions = listOf( CustomAccessibilityAction( label = "Open article", action = { openArticle() true } ), CustomAccessibilityAction( label = "Add to bookmarks", action = { addToBookmarks() true } ), ) } ) { Article( modifier = Modifier.clearAndSetSemantics { }, onClick = openArticle, ) BookmarkButton( modifier = Modifier.clearAndSetSemantics { }, onClick = addToBookmarks, ) }
في هذه الحالات، احرص على محو الدلالات الأصلية للعناصر الفرعية يدويًا
باستخدام المُعدِّل clearAndSetSemantics
، وذلك أثناء نقلها إلى
الإجراءات المخصّصة.
على سبيل المثال، عند استخدام ميزة "الوصول عبر مفتاح التحويل"، يتم فتح قائمتها عند اختيار الحاوية وتسرد الإجراءات المضمّنة المتاحة هناك:


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

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

في هذا المثال، يتم تنفيذ التقويم بأكمله كعنصر تركيبي واحد من المستوى المنخفض باستخدام العنصر التركيبي Layout
والرسم مباشرةً على Canvas
.
إذا لم يتم اتخاذ أي إجراء آخر، لن تتلقّى خدمات تسهيل الاستخدام معلومات كافية
عن محتوى العنصر القابل للتجميع واختيار المستخدم ضمن
التقويم. على سبيل المثال، إذا نقر أحد المستخدمين على اليوم الذي يتضمّن 17، لا يتلقّى
إطار عمل تسهيل الاستخدام سوى معلومات الوصف لعنصر التحكّم
في التقويم بأكمله. في هذه الحالة، ستُعلِن خدمة TalkBack للوصول الميسَّر عن "تقويم Google" أو "تقويم شهر نيسان (أبريل)"، ما سيترك المستخدم متسائلاً عن اليوم الذي تم اختياره. لجعل هذا العنصر القابل للتجميع أكثر
سهولة في الاستخدام، عليك إضافة معلومات دلالية يدويًا.
الشجرة المدمجة وغير المدمجة
كما ذكرنا سابقًا، قد لا يتم ضبط أيّ ملف شخصي من ملفات الدلالات أو أكثر في كل عنصر قابل للتجميع في شجرة واجهة المستخدم. عندما لا يكون لدى العنصر القابل للتجميع مجموعة من سمات الدلالات، لا يتم تضمينه كجزء من شجرة الدلالات. بهذه الطريقة، لا تحتوي شجرة الدلالات إلا على العقد التي تحتوي على معنى دلالي. ومع ذلك، في بعض الأحيان، لنقل المعنى الصحيح لما يظهر على الشاشة، يكون من المفيد أيضًا دمج أشجار فرعية معيّنة من العقد والتعامل معها كوحدة واحدة. بهذه الطريقة، يمكنك الاستدلال على مجموعة من العقد ككل، بدلاً من التعامل مع كل عقدة فرعية بشكلٍ فردي. كقاعدة عامة، تمثل كل عقدة في هذه الشجرة عنصرًا يمكن التركيز عليه عند استخدام خدمات تسهيل الاستخدام.
وButton
هو مثال على عنصر قابل للتجميع. يمكنك التعامل مع الزر
كعنصر واحد، على الرغم من أنّه قد يحتوي على عدّة عقد فرعية:
Button(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = null ) Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("Like") }
في شجرة الدلالات، يتم دمج سمات العناصر الفرعية للزر، ويُعرَض الزر كعقدة ورقة واحدة في الشجرة:

يمكن للعناصر القابلة للإنشاء والمُعدِّلات الإشارة إلى أنّها تريد دمج سمات دلالات
العناصر المشتقة من خلال استدعاء 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")
يتيح لك "أداة فحص التنسيق" عرض كلّ من شجرة "الدلالات" المدمجة وغير المدمجة، وذلك من خلال اختيار الشجرة المفضّلة في فلتر العرض:

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

تستخدِم أدوات المطابقة في "إطار عمل الاختبار" تلقائيًا شجرة الدلالات المدمجة.
لهذا السبب، يمكنك التفاعل مع Button
من خلال مطابقة النص المعروض داخله:
composeTestRule.onNodeWithText("Like").performClick()
يمكنك إلغاء هذا السلوك من خلال ضبط المَعلمة useUnmergedTree
لمطابقي
على true
، كما هو الحال مع المطابق onRoot
.
تعديل الشجرة
كما ذكرنا سابقًا، يمكنك إلغاء خصائص دلالية معيّنة أو محو بياناتها أو تغيير سلوك الدمج في الشجرة. وينطبق ذلك بشكل خاص عند إنشاء مكوّنات مخصّصة. بدون ضبط الخصائص وسلوك الدمج الصحيحَين، قد لا يكون بإمكانك الوصول إلى تطبيقك، وقد تؤدي الاختبارات إلى سلوك مختلف عن المتوقع. للاطّلاع على مزيد من المعلومات عن الاختبار، يمكنك الاطّلاع على دليل الاختبار.
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون لغة JavaScript غير مفعّلة.
- تسهيل الاستخدام في ميزة "الإنشاء"
- تصميم Material Design 2 في ميزة "الإنشاء"
- اختبار تنسيق ميزة "الإنشاء"