إتاحة إمكانية الوصول إلى العرض المخصَّص على Android TV
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
وعلى الرغم من أنّ العديد من تطبيقات Android TV مصمَّمة باستخدام مكوّنات Android الأصلية، فإنّها
من المهم أيضًا مراعاة إمكانية وصول الأطراف الثالثة
أطر العمل أو المكونات، خاصة عند استخدام طرق العرض المخصصة.
قد لا تعمل مكوّنات العرض المخصّص التي تتفاعل مباشرةً مع OpenGL أو Canvas بشكل جيد.
مع خدمات إمكانية الوصول مثل TalkBack والوصول عبر مفتاح التحويل.
يُرجى مراعاة بعض المشاكل التالية التي قد تحدث عند تبديل TalkBack.
عَلَى:
- قد يختفي تركيز تسهيل الاستخدام (مستطيل أخضر) في تطبيقك.
- قد يحدد تركيز تسهيل الاستخدام حدود الشاشة بأكملها.
- قد لا يكون تركيز تسهيل الاستخدام قابلاً للنقل.
- قد لا يكون لمفاتيح الاتجاهات الأربعة في لوحة التحكّم أي تأثير، حتى إذا كان الرمز يتعامل معها.
إذا لاحظت أيًا من هذه المشاكل في تطبيقك، تأكَّد من أنّ
يعرض التطبيق AccessibilityNodeInfo
الخاص به
خدمات الوصول بسهولة.
يقدِّم الجزء المتبقّي من هذا الدليل بعض الحلول وأفضل الممارسات لمعالجة هذه المشاكل.
تستخدم خدمات تسهيل الاستخدام أحداث لوحة التحكّم
السبب الجذري لهذه المشكلة هو أنّ المستخدمين يستهلكون الأحداث الرئيسية.
الشكل 1. مخطّطات بيانية توضّح كيفية عمل النظام عند تفعيل ميزة TalkBack وإيقافها
كما هو موضح في الشكل 1، عند تشغيل TalkBack، فإن أحداث لوحة التحكّم
لا يتم تمريرها إلى معالج لوحة التحكّم الذي يحدّده المطوّر. بدلاً من ذلك،
تتلقى خدمات إمكانية الوصول الأحداث الرئيسية حتى تتمكن من نقل
تركيز سهولة الوصول. وذلك لأنّ مكوّنات Android المخصّصة لا تعرض تلقائيًا
معلومات لخدمات تسهيل الاستخدام حول موضعها على الشاشة
لا يمكن لخدمات تسهيل الاستخدام نقل تركيز إمكانية الوصول لتمييزها.
تتأثر خدمات إمكانية الوصول الأخرى بالمثل: قد تتأثر أحداث لوحة التحكّم
يتم استهلاكها عند استخدام ميزة "الوصول عبر مفتاح تحكّم"
لأنّ أحداث لوحة التحكّم يتم إرسالها إلى خدمات تسهيل الاستخدام
تلك الخدمة لا تعرف مكان مكونات واجهة المستخدم في طريقة العرض المخصصة،
يجب تنفيذ AccessibilityNodeInfo
لتطبيقك لإعادة توجيه
الأحداث الرئيسية بشكل صحيح
لتوفير خدمات إمكانية الوصول بمعلومات كافية حول
الموقع الجغرافي ووصف طرق العرض المخصّصة، يمكنك تنفيذ AccessibilityNodeInfo
لكشف تفاصيل كل مكون.
تحديد العلاقة المنطقية بين وجهات النظر بحيث يمكن لخدمات إمكانية الوصول
إدارة التركيز، تنفيذ ExploreByTouchHelper
وتعيينه باستخدام
ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat)
لطرق العرض المخصّصة
عند تنفيذ الدالة ExploreByTouchHelper
، يمكنك إلغاء الطرق التجريدية الأربعة الخاصة بها:
Kotlin
// Return the virtual view ID whose view is covered by the input point (x, y).
protected fun getVirtualViewAt(x: Float, y: Float): Int
// Fill the virtual view ID list into the input parameter virtualViewIds.
protected fun getVisibleVirtualViews(virtualViewIds: List<Int>)
// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected fun onPopulateNodeForVirtualView(virtualViewId: Int, @NonNull node: AccessibilityNodeInfoCompat)
// Set the accessibility handling when perform action.
protected fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, @Nullable arguments: Bundle): Boolean
Java
// Return the virtual view ID whose view is covered by the input point (x, y).
protected int getVirtualViewAt(float x, float y)
// Fill the virtual view ID list into the input parameter virtualViewIds.
protected void getVisibleVirtualViews(List<Integer> virtualViewIds)
// For the view whose virtualViewId is the input virtualViewId, populate the
// accessibility node information into the AccessibilityNodeInfoCompat parameter.
protected void onPopulateNodeForVirtualView(int virtualViewId, @NonNull AccessibilityNodeInfoCompat node)
// Set the accessibility handling when perform action.
protected boolean onPerformActionForVirtualView(int virtualViewId, int action, @Nullable Bundle arguments)
لمزيد من التفاصيل، يُرجى مشاهدة مؤتمر Google I/O 2013 - تمكين المكفوفين وضعاف النظر
أدوات تسهيل الاستخدام على Android
أو يمكنك قراءة المزيد حول تعبئة أحداث تسهيل الاستخدام.
أفضل الممارسات
عيّنة
يمكنك الرجوع إلى نموذج إمكانية الوصول إلى العرض المخصّص في Android TV للاطلاع على أفضل ممارسات
إضافة دعم إمكانية الوصول إلى التطبيقات باستخدام طرق العرض المخصصة.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Custom view accessibility support on Android TV\n\nWhile many Android TV apps are built with native Android components, it's\nalso important to consider the accessibility of third-party\nframeworks or components, especially when using [custom views](https://developer.android.com/guide/topics/ui/custom-components).\n\nCustom view components interfacing directly with OpenGL or Canvas might not work well\nwith accessibility services like Talkback and Switch Access.\n\nConsider some of the following issues that might occur with Talkback switched\non:\n\n- The accessibility focus (a green rectangle) might disappear in your app.\n- The accessibility focus might select the boundary of the whole screen.\n- The accessibility focus might not be movable.\n- The four direction keys on the D-pad might have no effect, even if your code is handling them.\n\n\u003cbr /\u003e\n\nIf you observe any of these issues in your app, check that your\napp exposes its [`AccessibilityNodeInfo`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo)\ntree to the accessibility services.\n\nThe remainder of this guide provides some solutions and best practices to address these issues.\n\nD-pad events are consumed by accessibility services\n---------------------------------------------------\n\nThe root cause of this issue is that key events are consumed by accessibility\nservices.\n\n\n**Figure 1.** Diagrams depicting how the system functions with Talkback on and off.\n\nAs illustrated in figure 1, when Talkback is switched on, D-pad events\nare not passed to the D-pad handler defined by developer. Instead,\naccessibility services receive the key events so they can move the\naccessibility focus. Because custom Android components don't by default expose\ninformation to accessibility services about their position on the screen,\naccessibility services can't move the accessibility focus to highlight them.\n\nOther accessibility services are similarly affected: D-pad events might also be\nconsumed when using Switch Access.\n\nBecause D-pad events are submitted to accessibility services, and\nthat service doesn't know where UI components are in a custom view,\nyou must implement `AccessibilityNodeInfo` for your app to forward the\nkey events correctly.\n\nExpose information to accessibility services\n--------------------------------------------\n\nTo provide accessibility services with sufficient information about the\nlocation and description of custom views, implement [`AccessibilityNodeInfo`](/reference/android/view/accessibility/AccessibilityNodeInfo)\nto expose details for each component.\nTo define the logical relationship of views so that accessibility services can\nmanage focus, implement [`ExploreByTouchHelper`](https://developer.android.com/reference/androidx/customview/widget/ExploreByTouchHelper)\nand set it using\n[`ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat)`](https://developer.android.com/reference/androidx/core/view/ViewCompat#setAccessibilityDelegate(android.view.View,%20androidx.core.view.AccessibilityDelegateCompat))\nfor custom views.\n\nWhen implementing `ExploreByTouchHelper`, override its four abstract methods: \n\n### Kotlin\n\n```kotlin\n// Return the virtual view ID whose view is covered by the input point (x, y).\nprotected fun getVirtualViewAt(x: Float, y: Float): Int\n\n// Fill the virtual view ID list into the input parameter virtualViewIds.\nprotected fun getVisibleVirtualViews(virtualViewIds: List\u003cInt\u003e)\n\n// For the view whose virtualViewId is the input virtualViewId, populate the\n// accessibility node information into the AccessibilityNodeInfoCompat parameter.\nprotected fun onPopulateNodeForVirtualView(virtualViewId: Int, @NonNull node: AccessibilityNodeInfoCompat)\n\n// Set the accessibility handling when perform action.\nprotected fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, @Nullable arguments: Bundle): Boolean\n```\n\n### Java\n\n```java\n// Return the virtual view ID whose view is covered by the input point (x, y).\nprotected int getVirtualViewAt(float x, float y)\n\n// Fill the virtual view ID list into the input parameter virtualViewIds.\nprotected void getVisibleVirtualViews(List\u003cInteger\u003e virtualViewIds)\n\n// For the view whose virtualViewId is the input virtualViewId, populate the\n// accessibility node information into the AccessibilityNodeInfoCompat parameter.\nprotected void onPopulateNodeForVirtualView(int virtualViewId, @NonNull AccessibilityNodeInfoCompat node)\n\n// Set the accessibility handling when perform action.\nprotected boolean onPerformActionForVirtualView(int virtualViewId, int action, @Nullable Bundle arguments)\n```\n\nFor more details, watch [Google I/O 2013 - Enabling Blind and Low-Vision\nAccessibility on Android](https://www.youtube.com/watch?v=ld7kZRpMGb8&t=1196)\nor read more about [populating accessibility events](https://developer.android.com/guide/topics/ui/accessibility/custom-views#populate-events).\n\nBest practices\n--------------\n\n- **Required:** [`AccessibilityNodeInfo.getBoundsInScreen()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#getBoundsInScreen(android.graphics.Rect))\n must define the position of the component.\n\n- **Required:** [`AccessibilityNodeInfo.setVisibleToUser()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setVisibleToUser(boolean))\n must reflect the visibility of the component.\n\n- **Required:** [`AccessibilityNodeInfo.getContentDescription()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#getContentDescription())\n must specify the content description for Talkback to announce.\n\n- Specify [`AccessibilityNodeInfo.setClassName()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setClassName(java.lang.CharSequence))\n so services can distinguish the component type.\n\n- When implementing [`performAction()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#performAction(int)),\n reflect the action using a corresponding [`AccessibilityEvent`](https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent).\n\n- To implement more action types, such as `ACTION_CLICK`, invoke\n [`AccessibilityNodeInfo.addAction(ACTION_CLICK)`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#addAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction))\n using the corresponding logic in `performAction()`.\n\n- When applicable, reflect the component state for [`setFocusable()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setFocusable(boolean)),\n [`setClickable()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setClickable(boolean)),\n [`setScrollable()`](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setScrollable(boolean)),\n and similar methods.\n\n- Review the documentation for [`AccessibilityNodeInfo`](/reference/android/view/accessibility/AccessibilityNodeInfo)\n to identify other ways in which accessibility services can better interact with\n your components.\n\nSample\n------\n\nConsult the [custom view accessibility sample for Android TV](/training/tv/accessibility/custom-views-sample) to see best practices for\nadding accessibility support to apps using custom views."]]