TV 앱에는 TalkBack으로 앱 사용 이러한 사용자에게 더 나은 TalkBack 환경을 제공하기 위해 이 가이드의 각 섹션을 검토하고 사용할 수 있습니다. 앱에서 맞춤 뷰를 사용하는 경우 맞춤 API로 접근성을 지원하는 방법을 설명하는 해당하는 가이드 할 수 있습니다.
중첩 뷰 처리
중첩된 뷰는 TalkBack 사용자가 탐색하기 어려울 수 있습니다. 가능하면 항상 TalkBack으로 포커스할 수 있는 상위 뷰나 하위 뷰를 둘 다 지원할 수는 없습니다.
TalkBack에서 보기를 포커스 가능하게 설정하려면 focusable
및
focusableInTouchMode
속성을 true
로 설정합니다. 이 단계가 필요한 이유는
일부 TV 기기의 경우 TalkBack이 활성화되어 있는 동안 터치 모드를 시작하고 종료할 수 있습니다.
뷰에 포커스 불가능을 만들려면 focusable
를 설정하기만 하면 됩니다.
속성을 false
로 설정합니다. 그러나 조회 가능한 경우 (즉,
해당 AccessibilityNodeInfo
에 ACTION_CLICK
가 있음) 여전히
포커스 가능합니다
작업 설명 변경
기본적으로 TalkBack에서 '선택을 눌러 활성화'라고 알려줍니다. 활용 가능한 보기를 만들 수 있습니다. 일부 작업의 경우 '활성화'라는 용어 좋은 설명이 아닐 수 있습니다 받는사람 더 정확한 설명을 입력하면 됩니다.
Kotlin
findViewById<View>(R.id.custom_actionable_view).accessibilityDelegate = object : View.AccessibilityDelegate() { override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) { super.onInitializeAccessibilityNodeInfo(host, info) info.addAction( AccessibilityAction( AccessibilityAction.ACTION_CLICK.id, getString(R.string.custom_label) ) ) } }
자바
findViewById(R.id.custom_actionable_view).setAccessibilityDelegate(new AccessibilityDelegate() { @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); AccessibilityAction action = new AccessibilityAction( AccessibilityAction.ACTION_CLICK.getId(), getString(R.string.custom_label)); info.addAction(action); } });
슬라이더 지원 추가
TV의 TalkBack은 특별히 슬라이더를 지원합니다. 슬라이더 모드를 사용 설정하려면
RangeInfo
객체와 함께 뷰에 ACTION_SET_PROGRESS
을 추가합니다.
사용자가 TV 리모컨의 가운데 버튼을 눌러 슬라이더 모드로 전환합니다.
이 모드에서 화살표 버튼을 누르면 ACTION_SCROLL_FORWARD
이 생성되고
ACTION_SCROLL_BACKWARD
접근성 작업
다음 예에서는 1~10 사이의 볼륨 슬라이더를 구현합니다.
Kotlin
/** * This example only provides slider functionality for TalkBack users. Additional logic should * be added for other users. Such logic may reuse the increase and decrease methods. */ class VolumeSlider(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) { private val min = 1 private val max = 10 private var current = 5 private var textView: TextView? = null init { isFocusable = true isFocusableInTouchMode = true val rangeInfo = AccessibilityNodeInfo.RangeInfo( AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_INT, min.toFloat(), max.toFloat(), current.toFloat() ) accessibilityDelegate = object : AccessibilityDelegate() { override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) { super.onInitializeAccessibilityNodeInfo(host, info) info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_PROGRESS) info.rangeInfo = rangeInfo } override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean { if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.id) { increase() return true } if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD.id) { decrease() return true } return super.performAccessibilityAction(host, action, args) } } } override fun onFinishInflate() { super.onFinishInflate() textView = findViewById(R.id.text) textView!!.text = context.getString(R.string.level, current) } private fun increase() { update((current + 1).coerceAtMost(max)) } private fun decrease() { update((current - 1).coerceAtLeast(min)) } private fun update(newLevel: Int) { if (textView == null) { return } val newText = context.getString(R.string.level, newLevel) // Update the user interface with the new volume. textView!!.text = newText // Announce the new volume. announceForAccessibility(newText) current = newLevel } }
Java
/** * This example only provides slider functionality for TalkBack users. Additional logic should * be added for other users. Such logic can reuse the increase and decrease methods. */ public class VolumeSlider extends LinearLayout { private final int min = 1; private final int max = 10; private int current = 5; private TextView textView; public VolumeSlider(Context context, AttributeSet attrs) { super(context, attrs); setFocusable(true); setFocusableInTouchMode(true); RangeInfo rangeInfo = new RangeInfo(RangeInfo.RANGE_TYPE_INT, min, max, current); setAccessibilityDelegate( new AccessibilityDelegate() { @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); info.addAction(AccessibilityAction.ACTION_SET_PROGRESS); info.setRangeInfo(rangeInfo); } @Override public boolean performAccessibilityAction(View host, int action, Bundle args) { if (action == AccessibilityAction.ACTION_SCROLL_FORWARD.getId()) { increase(); return true; } if (action == AccessibilityAction.ACTION_SCROLL_BACKWARD.getId()) { decrease(); return true; } return super.performAccessibilityAction(host, action, args); } }); } @Override protected void onFinishInflate() { super.onFinishInflate(); textView = findViewById(R.id.text); textView.setText(getContext().getString(R.string.level, current)); } private void increase() { update(Math.min(current + 1, max)); } private void decrease() { update(Math.max(current - 1, min)); } private void update(int newLevel) { if (textView == null) { return; } String newText = getContext().getString(R.string.level, newLevel); // Update the user interface with the new volume. textView.setText(newText); // Announce the new volume. announceForAccessibility(newText); current = newLevel; } }