Хотя многие приложения для Android TV созданы с использованием нативных компонентов Android, важно также учитывать доступность сторонних фреймворков или компонентов, особенно при использовании пользовательских представлений .
Пользовательские компоненты представления, напрямую взаимодействующие с OpenGL или Canvas, могут плохо работать со службами обеспечения доступности, такими как Talkback и Switch Access.
Рассмотрим некоторые из следующих проблем, которые могут возникнуть при включенной функции Talkback:
- В вашем приложении может исчезнуть индикатор доступности (зеленый прямоугольник).
- Функция "Фокус доступности" может выбирать границы всего экрана.
- Акцент на доступности может быть неизменным.
- Четыре клавиши направления на D-pad могут не оказывать никакого эффекта, даже если ваш код их обрабатывает.
Если вы обнаружите какие-либо из этих проблем в своем приложении, убедитесь, что ваше приложение предоставляет доступ к дереву AccessibilityNodeInfo службам специальных возможностей.
В оставшейся части этого руководства представлены некоторые решения и лучшие практики для решения этих проблем.
События, возникающие при нажатии на D-pad, обрабатываются службами обеспечения доступности.
Основная причина этой проблемы заключается в том, что ключевые события обрабатываются службами обеспечения доступности.

Как показано на рисунке 1, когда функция Talkback включена, события D-pad не передаются обработчику D-pad, определенному разработчиком. Вместо этого события клавиш передаются службам специальных возможностей, которые могут перемещать фокус специальных возможностей. Поскольку пользовательские компоненты Android по умолчанию не предоставляют службам специальных возможностей информацию о своем положении на экране, службы специальных возможностей не могут перемещать фокус специальных возможностей для их подсветки.
Аналогичным образом затронуты и другие службы специальных возможностей: события нажатия D-pad могут также обрабатываться при использовании функции Switch Access.
Поскольку события D-pad передаются в службы специальных возможностей, а эта служба не знает, где находятся компоненты пользовательского интерфейса в пользовательском представлении, для корректной передачи событий нажатия клавиш вашему приложению необходимо реализовать AccessibilityNodeInfo .
Предоставьте доступ к информации службам обеспечения доступности.
Чтобы предоставить службам доступности достаточно информации о местоположении и описании пользовательских представлений, реализуйте AccessibilityNodeInfo , чтобы отображать подробные сведения о каждом компоненте. Для определения логической связи представлений, позволяющей службам доступности управлять фокусом, реализуйте интерфейс ExploreByTouchHelper и устанавливайте его с помощью ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat) для пользовательских представлений.
При реализации ExploreByTouchHelper переопределите его четыре абстрактных метода:
Котлин
// 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» или прочитайте подробнее о заполнении событий доступности .
Передовые методы
Обязательно:
AccessibilityNodeInfo.getBoundsInScreen()должен определять положение компонента.Обязательно:
AccessibilityNodeInfo.setVisibleToUser()должен отображать видимость компонента.Обязательно:
AccessibilityNodeInfo.getContentDescription()должен указывать описание контента, которое будет озвучиваться Talkback.Укажите метод
AccessibilityNodeInfo.setClassName(), чтобы службы могли различать тип компонента.При реализации метода
performAction()отразите действие с помощью соответствующегоAccessibilityEvent.Для реализации дополнительных типов действий, таких как
ACTION_CLICK, вызовитеAccessibilityNodeInfo.addAction(ACTION_CLICK)используя соответствующую логику вperformAction().При необходимости отражайте состояние компонента для методов
setFocusable(),setClickable(),setScrollable()и аналогичных.Изучите документацию по
AccessibilityNodeInfo, чтобы узнать о других способах улучшения взаимодействия служб доступности с вашими компонентами.
Образец
Чтобы ознакомиться с рекомендациями по добавлению поддержки специальных возможностей в приложения, использующие пользовательские представления, обратитесь к примеру использования пользовательских представлений для Android TV .