많은 Android TV 앱이 기본 Android 구성요소로 빌드되지만 서드 파티 프레임워크 또는 구성요소의 접근성도 고려하는 것이 중요합니다. 특히 맞춤 뷰를 사용하는 경우에 그렇습니다.
OpenGL 또는 Canvas와 직접 상호작용하는 맞춤 뷰 구성요소는 TalkBack 및 스위치 제어와 같은 접근성 서비스와 잘 작동하지 않을 수 있습니다.
TalkBack이 사용 설정된 상태에서 발생할 수 있는 다음 문제를 고려하세요.
- 접근성 포커스 (녹색 직사각형)가 앱에서 사라질 수 있습니다.
- 접근성 포커스가 전체 화면의 경계를 선택할 수 있습니다.
- 접근성 포커스를 이동할 수 없을 수 있습니다.
- 코드가 D패드 방향 키를 처리하더라도 D패드의 4방향 키가 아무런 영향을 미치지 않을 수 있습니다.
앱에서 이러한 문제가 관찰되면 앱이
AccessibilityNodeInfo 트리를 접근성 서비스에 노출하는지 확인하세요.
이 가이드의 나머지 부분에서는 이러한 문제를 해결하기 위한 몇 가지 솔루션과 권장사항을 제공합니다.
D패드 이벤트는 접근성 서비스에서 사용됩니다.
이 문제의 근본 원인은 키 이벤트가 접근성 서비스에서 사용되기 때문입니다.
그림 1에 나와 있듯이 TalkBack이 사용 설정되면 D패드 이벤트가 개발자가 정의한 D패드 핸들러에 전달되지 않습니다. 대신 접근성 서비스는 접근성 포커스를 이동할 수 있도록 키 이벤트를 수신합니다. 맞춤 Android 구성요소는 기본적으로 화면에서의 위치에 관한 정보를 접근성 서비스에 노출하지 않으므로 접근성 서비스는 접근성 포커스를 이동하여 강조표시할 수 없습니다.
다른 접근성 서비스도 마찬가지로 영향을 받습니다. 스위치 제어를 사용할 때 D패드 이벤트가 사용될 수도 있습니다.
D패드 이벤트가 접근성 서비스에 제출되고 서비스가 맞춤 뷰에서 UI 구성요소가 있는 위치를 알지 못하므로 앱이 키 이벤트를 올바르게 전달하려면 AccessibilityNodeInfo를 구현해야 합니다.
접근성 서비스에 정보 노출
맞춤 뷰의 위치
와 설명에 관한 충분한 정보를 접근성 서비스에 제공하려면 AccessibilityNodeInfo를 구현하여
각 구성요소의 세부정보를 노출하세요. 접근성 서비스가 포커스를 관리할 수 있도록 뷰의 논리적 관계를 정의하려면
ExploreByTouchHelper를 구현하고 맞춤 뷰에
ViewCompat.setAccessibilityDelegate(View, AccessibilityDelegateCompat)
를 사용하여 설정하세요.
ExploreByTouchHelper를 구현할 때는 추상 메서드 4개를 재정의합니다.
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
자바
// 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용 맞춤 뷰 접근성 샘플을 참고하세요.