많은 Android TV 앱이 네이티브 Android 구성요소로 빌드되지만 특히 맞춤 뷰를 사용할 때 서드 파티 프레임워크 또는 구성요소의 접근성을 고려하는 것도 중요합니다.
OpenGL 또는 캔버스와 직접 상호작용하는 맞춤 뷰 구성요소는 TalkBack, 스위치 제어와 같은 접근성 서비스에서 제대로 작동하지 않을 수 있습니다.
TalkBack이 사용 설정된 상태에서 발생할 수 있는 다음과 같은 문제를 고려하세요.
- 앱에서 접근성 포커스 (녹색 직사각형)가 사라질 수 있습니다.
- 접근성 포커스가 전체 화면의 경계를 선택할 수 있습니다.
- 접근성 포커스를 이동할 수 없습니다.
- D패드의 4개 방향 키는 코드에서 처리하더라도 아무런 영향을 미치지 않을 수 있습니다.
앱에서 이러한 문제가 발견되면 앱에서 AccessibilityNodeInfo
트리를 접근성 서비스에 노출하는지 확인하세요.
이 가이드의 나머지 부분에서는 이러한 문제를 해결하기 위한 몇 가지 솔루션과 권장사항을 제공합니다.
접근성 서비스에서 사용하는 D패드 이벤트
이 문제의 근본 원인은 접근성 서비스에서 주요 이벤트를 사용하기 때문입니다.
그림 1과 같이 TalkBack이 켜져 있으면 D패드 이벤트가 개발자가 정의한 D패드 핸들러로 전달되지 않습니다. 대신 접근성 서비스는 키 이벤트를 수신하여 접근성 포커스를 이동할 수 있습니다. 맞춤 Android 구성요소는 기본적으로 화면상의 위치에 관한 정보를 접근성 서비스에 노출하지 않으므로 접근성 서비스에서 접근성 포커스를 이동하여 강조 표시할 수 없습니다.
다른 접근성 서비스도 마찬가지로 영향을 받습니다. 스위치 제어를 사용할 때 D패드 이벤트가 소비될 수도 있습니다.
D패드 이벤트는 접근성 서비스에 제출되고 이 서비스는 맞춤 뷰에서 UI 구성요소의 위치를 알지 못하므로 앱이 키 이벤트를 올바르게 전달하도록 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에서 시각장애인 및 저시력 접근성 지원을 시청하거나 접근성 이벤트 채우기를 참고하세요.
권장사항
필수:
AccessibilityNodeInfo.getBoundsInScreen()
는 구성요소의 위치를 정의해야 합니다.필수:
AccessibilityNodeInfo.setVisibleToUser()
는 구성요소의 공개 상태를 반영해야 합니다.필수:
AccessibilityNodeInfo.getContentDescription()
에서는 TalkBack에서 공지할 콘텐츠 설명을 지정해야 합니다.서비스가 구성요소 유형을 구별할 수 있도록
AccessibilityNodeInfo.setClassName()
를 지정합니다.performAction()
를 구현할 때 상응하는AccessibilityEvent
를 사용하여 작업을 반영합니다.ACTION_CLICK
와 같은 추가 작업 유형을 구현하려면performAction()
에서 상응하는 로직을 사용하여AccessibilityNodeInfo.addAction(ACTION_CLICK)
를 호출합니다.해당하는 경우
setFocusable()
,setClickable()
,setScrollable()
및 이와 유사한 메서드의 구성요소 상태를 반영합니다.접근성 서비스가 구성요소와 더 잘 상호작용할 수 있는 다른 방법을 알아보려면
AccessibilityNodeInfo
문서를 검토하세요.
샘플
맞춤 뷰를 사용하여 앱에 접근성 지원을 추가하는 것과 관련된 권장사항을 확인하려면 Android TV용 맞춤 뷰 접근성 샘플을 참고하세요.