إذا كان تطبيقك يتطلب مكوّن طريقة عرض مخصّصة، عليك تسهيل الوصول إلى العرض. يمكن أن تؤدي الخطوات التالية إلى تحسين إمكانية الوصول إلى العرض المخصص، كما هو موضح في هذه الصفحة:
- تعامل مع نقرات وحدة التحكّم الاتجاهات.
- تنفيذ طرق واجهة برمجة التطبيقات Accessibility API.
- إرسال عناصر
AccessibilityEvent
خاصة بعرضك المخصّص. - عليك تعبئة
AccessibilityEvent
وAccessibilityNodeInfo
للعرض الخاص بك.
التعامل مع نقرات وحدة التحكّم الاتجاهية
في معظم الأجهزة، يؤدي النقر على عرض باستخدام وحدة التحكّم في الاتجاهات إلى إرسال
KeyEvent
مع
KEYCODE_DPAD_CENTER
إلى العرض الذي يتم التركيز عليه حاليًا. تتعامل جميع طرق العرض العادية في Android مع
KEYCODE_DPAD_CENTER
بشكل مناسب. عند إنشاء عنصر تحكّم مخصّص
View
، تأكَّد من أنّ هذا الحدث له نفس تأثير النقر على طريقة العرض على الشاشة التي تعمل باللمس.
يجب أن يتعامل عنصر التحكّم المخصّص مع
KEYCODE_ENTER
بالطريقة نفسها التي يعامل بها KEYCODE_DPAD_CENTER
. هذا يجعل التفاعل مع لوحة المفاتيح
الكاملة أسهل للمستخدمين.
تنفيذ طرق واجهة برمجة التطبيقات Accessibility API
أحداث تسهيل الاستخدام هي رسائل عن تفاعلات المستخدمين مع مكوّنات الواجهة المرئية في تطبيقك. تعالج خدمات تسهيل الاستخدام هذه الرسائل، التي
تستخدم المعلومات في هذه الأحداث لتقديم ملاحظات وآراء تكميلية. تُعدّ طرق تسهيل الاستخدام جزءًا من فئتي View
وView.AccessibilityDelegate
. إليك الطرق:
dispatchPopulateAccessibilityEvent()
onPopulateAccessibilityEvent()
لطريقة العرض هذه، ثم الطريقة dispatchPopulateAccessibilityEvent()
لكل عنصر ثانوي في هذا الملف الشخصي. onInitializeAccessibilityEvent()
TextView
أو Button
البسيط، يمكنك إلغاء هذه الطريقة وضبط المعلومات الإضافية حول طريقة العرض، مثل نوع حقل كلمة المرور أو نوع مربّع الاختيار أو الحالات التي توفّر تفاعل المستخدم أو ملاحظات بشأن الحدث، وذلك باستخدام هذه الطريقة. في حال إلغاء هذه الطريقة، يمكنك طلب التنفيذ المميّز وتعديل السمات
التي لم يتم ضبطها من خلال الفئة المتميّزة فقط.onInitializeAccessibilityNodeInfo()
View
التلقائي على مجموعة عادية من سمات الملفات الشخصية، ولكن إذا كان طريقة العرض المخصّصة توفّر تحكّمًا تفاعليًا يتجاوز TextView
أو Button
البسيط، يمكنك إلغاء هذه الطريقة وضبط المعلومات الإضافية عن ملفك الشخصي في عنصر AccessibilityNodeInfo
الذي تتم معالجته بهذه الطريقة.onPopulateAccessibilityEvent()
AccessibilityEvent
للعرض. ويُسمّى أيضًا إذا كانت طريقة العرض ثانويّة لطريقة عرض تؤدي إلى إنشاء حدث لتسهيل الاستخدام.
onRequestSendAccessibilityEvent()
AccessibilityEvent
. تسمح هذه الخطوة للعرض الرئيسي بتعديل حدث تسهيل الاستخدام
باستخدام معلومات إضافية. لا تنفِّذ هذه الطريقة إلا إذا كان من الممكن أن يتضمن العرض المخصَّص طرق عرض فرعية
وإذا كان بإمكان طريقة العرض الرئيسية توفير معلومات السياق إلى حدث تسهيل الاستخدام الذي يكون مفيدًا لخدمات تسهيل الاستخدام.sendAccessibilityEvent()
- يستدعي النظام هذه الطريقة عندما يتّخذ المستخدم إجراءً بشأن مشاهدة. يتم تصنيف الحدث بنوع إجراء المستخدم، مثل
TYPE_VIEW_CLICKED
. بشكلٍ عام، عليك إرسالAccessibilityEvent
كلما تغيّر محتوى طريقة العرض المخصّصة. sendAccessibilityEventUnchecked()
- تُستخدم هذه الطريقة عندما يحتاج رمز الاتصال إلى التحكّم مباشرةً في عملية التحقّق من تفعيل
تسهيل الاستخدام على الجهاز
(
AccessibilityManager.isEnabled()
). في حال تنفيذ هذه الطريقة، يمكنك إجراء المكالمة كما لو كانت ميزة تسهيل الاستخدام مفعَّلة، بغض النظر عن إعداد النظام. لا تحتاج عادةً إلى تنفيذ هذه الطريقة للعرض المخصّص. dispatchPopulateAccessibilityEvent()
onInitializeAccessibilityEvent()
onInitializeAccessibilityNodeInfo()
onPopulateAccessibilityEvent()
TYPE_VIEW_CLICKED
TYPE_VIEW_FOCUSED
TYPE_VIEW_HOVER_ENTER
TYPE_VIEW_HOVER_EXIT
TYPE_VIEW_LONG_CLICKED
TYPE_VIEW_SCROLLED
- أنشئ
AccessibilityEvent
مناسبًا لإجراء النقرة المفسَّرة. - يمكنك تفعيل خدمات تسهيل الاستخدام لتنفيذ إجراء النقر المخصّص للمستخدمين الذين يتعذّر عليهم استخدام شاشة تعمل باللمس.
لإتاحة إمكانية الوصول، يمكنك إلغاء أساليب تسهيل الاستخدام السابقة وتنفيذها مباشرةً في فئة العرض المخصّص.
يمكنك على الأقل تنفيذ طرق تسهيل الاستخدام التالية لفئة طريقة العرض المخصّصة:
لمزيد من المعلومات حول تنفيذ هذه الطرق، راجِع القسم حول تعبئة أحداث تسهيل الاستخدام.
إرسال أحداث تسهيل الاستخدام
استنادًا إلى تفاصيل طريقة العرض المخصّصة، قد تحتاج إلى إرسال
عناصر AccessibilityEvent
في أوقات مختلفة أو بالنسبة إلى الأحداث التي لم تتم معالجتها من خلال
طريقة التنفيذ التلقائية. توفّر الفئة View
عملية تنفيذ تلقائية لأنواع الأحداث التالية:
بشكل عام، يجب إرسال AccessibilityEvent
كلما تغيّر محتوى طريقة العرض المخصّصة. على سبيل المثال، إذا كنت تنفّذ شريط تمرير مخصّص يتيح للمستخدم اختيار
قيمة رقمية عن طريق الضغط على مفتاح السهم المتّجه لليسار أو اليمين، يجب أن تصدر طريقة العرض المخصّصة حدث
TYPE_VIEW_TEXT_CHANGED
كلما تغيّرت قيمة شريط التمرير. يوضّح نموذج الرمز البرمجي التالي استخدام طريقة sendAccessibilityEvent()
للإبلاغ عن هذا الحدث.
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when(keyCode) { KeyEvent.KEYCODE_DPAD_LEFT -> { currentValue-- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) true } ... } }
Java
@Override public boolean onKeyUp (int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { currentValue--; sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); return true; } ... }
تعبئة أحداث تسهيل الاستخدام
يتضمّن كل AccessibilityEvent
مجموعة من الخصائص المطلوبة التي تصف الحالة الحالية للعرض. وتتضمن هذه السمات عناصر مثل اسم فئة العرض ووصف المحتوى والحالة التي تم وضع علامة عليها. تم توضيح السمات المحددة المطلوبة لكل نوع من أنواع الأحداث
في
AccessibilityEvent
المستندات المرجعية.
توفِّر عملية تنفيذ View
قيمًا تلقائية لهذه
السمات المطلوبة. ويتم توفير العديد من هذه القيم تلقائيًا، بما في ذلك اسم الفئة والطابع الزمني للحدث. إذا كنت تقوم بإنشاء مكون عرض مخصص، يجب عليك تقديم معلومات حول محتوى العرض وخصائصه. يمكن أن تكون هذه المعلومات بسيطة مثل تسمية زر ويمكن أن
تتضمن معلومات الحالة الإضافية التي تريد إضافتها إلى الحدث.
استخدِم طريقتَي
onPopulateAccessibilityEvent()
و
onInitializeAccessibilityEvent()
لتعبئة المعلومات أو تعديلها في AccessibilityEvent
. استخدِم طريقة onPopulateAccessibilityEvent()
تحديدًا لإضافة أو تعديل المحتوى النصي للفعالية، والذي يتم تحويله إلى طلبات مسموعة من خلال خدمات تسهيل الاستخدام مثل TalkBack. استخدِم طريقة onInitializeAccessibilityEvent()
لملء معلومات إضافية
حول الحدث، مثل حالة اختيار العرض.
بالإضافة إلى ذلك، نفِّذ
طريقة onInitializeAccessibilityNodeInfo()
. تستخدم خدمات تسهيل الاستخدام كائنات AccessibilityNodeInfo
التي تتم تعبئتها بهذه الطريقة لفحص التسلسل الهرمي لطريقة العرض الذي ينشئ حدث تسهيل الاستخدام بعد تلقّيه وتقديم الملاحظات المناسبة للمستخدمين.
يوضّح مثال الرمز التالي كيفية إلغاء هذه الطرق الثلاث في طريقة العرض:
Kotlin
override fun onPopulateAccessibilityEvent(event: AccessibilityEvent?) { super.onPopulateAccessibilityEvent(event) // Call the super implementation to populate its text for the // event. Then, add text not present in a super class. // You typically only need to add the text for the custom view. if (text?.isNotEmpty() == true) { event?.text?.add(text) } } override fun onInitializeAccessibilityEvent(event: AccessibilityEvent?) { super.onInitializeAccessibilityEvent(event) // Call the super implementation to let super classes // set appropriate event properties. Then, add the new checked // property that is not supported by a super class. event?.isChecked = isChecked() } override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo?) { super.onInitializeAccessibilityNodeInfo(info) // Call the super implementation to let super classes set // appropriate info properties. Then, add the checkable and checked // properties that are not supported by a super class. info?.isCheckable = true info?.isChecked = isChecked() // You typically only need to add the text for the custom view. if (text?.isNotEmpty() == true) { info?.text = text } }
Java
@Override public void onPopulateAccessibilityEvent(AccessibilityEvent event) { super.onPopulateAccessibilityEvent(event); // Call the super implementation to populate its text for the // event. Then, add the text not present in a super class. // You typically only need to add the text for the custom view. CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { event.getText().add(text); } } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); // Call the super implementation to let super classes // set appropriate event properties. Then, add the new checked // property that is not supported by a super class. event.setChecked(isChecked()); } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); // Call the super implementation to let super classes set // appropriate info properties. Then, add the checkable and checked // properties that are not supported by a super class. info.setCheckable(true); info.setChecked(isChecked()); // You typically only need to add the text for the custom view. CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { info.setText(text); } }
يمكنك تنفيذ هذه الطرق مباشرةً في فئة العرض المخصّص.
توفير سياق مخصّص لإمكانية الوصول
يمكن لخدمات تسهيل الاستخدام فحص العرض الهرمي الذي يتضمّن طرق العرض لمكوِّن واجهة المستخدم الذي ينشئ حدث إمكانية الوصول. يتيح هذا لخدمات إمكانية الوصول توفير معلومات سياقية أكثر ثراءً لمساعدة المستخدمين.
هناك حالات لا يمكن فيها لخدمات تسهيل الاستخدام الحصول على معلومات كافية من العرض الهرمي لطريقة العرض. ومن الأمثلة على ذلك عنصر تحكم واجهة مخصص يحتوي على منطقتين أو أكثر يمكن النقر عليهما بشكل منفصل، مثل عنصر تحكم في التقويم. في هذه الحالة، لا يمكن للخدمات الحصول على المعلومات الكافية لأن الأقسام الفرعية القابلة للنقر ليست جزءًا من التسلسل الهرمي لطريقة العرض.
![](https://developer.android.com/static/guide/topics/ui/accessibility/calendar.png?authuser=5&hl=ar)
الشكل 1. عرض مخصّص للتقويم مع عناصر يوم يمكن اختيارها
في المثال 1، يتم تنفيذ التقويم بالكامل كعرض واحد، لذا لا تتلقى خدمات تسهيل الاستخدام معلومات كافية حول محتوى طريقة العرض واختيار المستخدم داخل طريقة العرض ما لم يقدّم مطوّر البرامج معلومات إضافية. على سبيل المثال، إذا نقر مستخدم على اليوم المصنّف 17، لن يتلقّى إطار عمل تسهيل الاستخدام سوى معلومات الوصف لعنصر التحكّم في التقويم بأكمله. في هذه الحالة، تُعلن خدمة إمكانية الوصول في TalkBack عن "التقويم" أو "تقويم نيسان (أبريل)"، ولا يعرف المستخدم اليوم الذي تم اختياره.
لتوفير معلومات كافية حول السياق لخدمات تسهيل الاستخدام في مثل هذه الحالات، يوفّر الإطار طريقة لتحديد العرض الهرمي لطريقة العرض الافتراضية. يُعدّ التسلسل الهرمي لطريقة العرض الافتراضية طريقة يمكن لمطوّري التطبيقات من خلالها توفير تسلسل هرمي تكميلي لخدمات تسهيل الاستخدام التي تتطابق إلى حدّ كبير مع المعلومات التي تظهر على الشاشة. يتيح هذا النهج لخدمات إمكانية الوصول توفير معلومات سياق أكثر فائدة للمستخدمين.
قد تكون هناك حاجة إلى عرض هرمي افتراضي لعرض الإعلانات، وهي واجهة مستخدم تحتوي على مجموعة من عناصر التحكّم في View
ذات الوظائف المرتبطة بشكل وثيق، حيث يؤثر الإجراء في عنصر تحكّم واحد في محتوى عنصر واحد أو أكثر، مثل أداة اختيار الأرقام مع زرَّين منفصلَين للأعلى وللأسفل. في هذه الحالة، لا يمكن لخدمات تسهيل الاستخدام الحصول على المعلومات الكافية لأنّ إجراءً معيّنًا على أحد عناصر التحكّم يؤدي إلى تغيير المحتوى في عنصر تحكّم آخر، وقد لا تكون علاقة عناصر التحكّم هذه واضحة للخدمة.
للتعامل مع هذا الموقف، يمكنك تجميع عناصر التحكم ذات الصلة مع عرض شامل وتوفير تسلسل هرمي لعرض افتراضي من هذه الحاوية لتمثيل المعلومات والسلوك التي تقدمها عناصر التحكم بشكلٍ واضح.
لتوفير تسلسل هرمي افتراضي لطريقة العرض، يمكنك إلغاء طريقة
getAccessibilityNodeProvider()
في طريقة العرض المخصّصة أو مجموعة المشاهدة المخصّصة وعرض تنفيذ
AccessibilityNodeProvider
.
يمكنك تنفيذ تسلسل هرمي لطريقة العرض الافتراضية باستخدام Support Library مع طريقة
ViewCompat.getAccessibilityNodeProvider()
وتقديم عملية تنفيذ من خلال
AccessibilityNodeProviderCompat
.
لتبسيط مهمة توفير المعلومات لخدمات تسهيل الاستخدام وإدارة
التركيز على تسهيل الاستخدام، يمكنك بدلاً من ذلك استخدام
ExploreByTouchHelper
.
وهو يوفر AccessibilityNodeProviderCompat
ويمكن إرفاقه كمشاهدة
AccessibilityDelegateCompat
من خلال طلب الرقم
setAccessibilityDelegate
.
على سبيل المثال، يمكنك مراجعة
ExploreByTouchHelperActivity
.
يتم أيضًا استخدام ExploreByTouchHelper
من خلال التطبيقات المصغّرة لأُطر العمل، مثل
CalendarView
، من خلال
عرضها الفرعي
SimpleMonthView
.
التعامل مع أحداث اللمس المخصّصة
قد تتطلب عناصر التحكّم في العرض المخصَّص سلوكًا غير عادي لحدث اللمس، كما هو موضَّح في الأمثلة التالية.
تحديد الإجراءات المستندة إلى النقرات
إذا كانت الأداة تستخدم الواجهة
OnClickListener
أو
OnLongClickListener
،
سيعالج النظام الإجراءَين
ACTION_CLICK
و
ACTION_LONG_CLICK
نيابةً عنك. إذا كان تطبيقك يستخدم أداة أكثر تخصيصًا تعتمد على واجهة
OnTouchListener
،
حدِّد معالجات مخصّصة لإجراءات تسهيل الاستخدام المستندة إلى النقر. لإجراء ذلك، عليك استدعاء الإجراء
replaceAccessibilityAction()
لكل إجراء، كما هو موضّح في مقتطف الرمز التالي:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Assumes that the widget is designed to select text when tapped, and selects // all text when tapped and held. In its strings.xml file, this app sets // "select" to "Select" and "select_all" to "Select all". ViewCompat.replaceAccessibilityAction( binding.textSelectWidget, ACTION_CLICK, getString(R.string.select) ) { view, commandArguments -> selectText() } ViewCompat.replaceAccessibilityAction( binding.textSelectWidget, ACTION_LONG_CLICK, getString(R.string.select_all) ) { view, commandArguments -> selectAllText() } }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Assumes that the widget is designed to select text when tapped, and select // all text when tapped and held. In its strings.xml file, this app sets // "select" to "Select" and "select_all" to "Select all". ViewCompat.replaceAccessibilityAction( binding.textSelectWidget, ACTION_CLICK, getString(R.string.select), (view, commandArguments) -> selectText()); ViewCompat.replaceAccessibilityAction( binding.textSelectWidget, ACTION_LONG_CLICK, getString(R.string.select_all), (view, commandArguments) -> selectAllText()); }
إنشاء أحداث مخصّصة للنقر
يمكن أن يستخدم عنصر التحكّم المخصّص
طريقة الاستماع onTouchEvent(MotionEvent)
لاكتشاف حدثَي
ACTION_DOWN
وACTION_UP
وبدء
حدث نقرة خاصة. للحفاظ على التوافق مع خدمات إمكانية الوصول، يجب على الرمز الذي
يعالج حدث النقر المخصّص هذا تنفيذ ما يلي:
للتعامل مع هذه المتطلبات بكفاءة، يجب أن يلغي الرمز طريقة
performClick()
،
التي يجب أن تستدعي التنفيذ الممتاز لهذه الطريقة، ثم تنفيذ أي إجراءات
مطلوبة من خلال حدث النقر. عند رصد إجراء النقر المخصّص، يجب أن يستدعي هذا الرمز طريقة performClick()
. يوضح مثال التعليمة البرمجية التالي هذا النمط.
Kotlin
class CustomTouchView(context: Context) : View(context) { var downTouch = false override fun onTouchEvent(event: MotionEvent): Boolean { super.onTouchEvent(event) // Listening for the down and up touch events. return when (event.action) { MotionEvent.ACTION_DOWN -> { downTouch = true true } MotionEvent.ACTION_UP -> if (downTouch) { downTouch = false performClick() // Call this method to handle the response and // enable accessibility services to // perform this action for a user who can't // tap the touchscreen. true } else { false } else -> false // Return false for other touch events. } } override fun performClick(): Boolean { // Calls the super implementation, which generates an AccessibilityEvent // and calls the onClick() listener on the view, if any. super.performClick() // Handle the action for the custom click here. return true } }
Java
class CustomTouchView extends View { public CustomTouchView(Context context) { super(context); } boolean downTouch = false; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); // Listening for the down and up touch events switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downTouch = true; return true; case MotionEvent.ACTION_UP: if (downTouch) { downTouch = false; performClick(); // Call this method to handle the response and // enable accessibility services to // perform this action for a user who can't // tap the touchscreen. return true; } } return false; // Return false for other touch events. } @Override public boolean performClick() { // Calls the super implementation, which generates an AccessibilityEvent // and calls the onClick() listener on the view, if any. super.performClick(); // Handle the action for the custom click here. return true; } }
يساعد النمط السابق على ضمان توافق حدث النقر المخصّص مع خدمات تسهيل الاستخدام من خلال استخدام طريقة performClick()
لإنشاء حدث تسهيل الاستخدام وتوفير نقطة دخول لخدمات تسهيل الاستخدام للتصرف نيابةً عن مستخدم ينفّذ حدث النقر المخصّص.