TV アプリで TalkBack をサポートする
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
TV アプリのユースケースによっては、
TalkBack: アプリを使用します。これらのデバイスで TalkBack をより快適に利用するには、
ユーザーを確認するには、このガイドの各セクションを確認し、
できます。アプリでカスタムビューを使用している場合は、
対応するガイドをご覧ください。
できます。
ネストされたビューを処理する
ネストされたビューは、TalkBack ユーザーが操作しにくいことがあります。可能な限り
TalkBack でフォーカス可能な親ビューまたは子ビューのどちらかのみです。両方を同時に指定することはできません。
TalkBack でビューをフォーカスできるようにするには、focusable
と
focusableInTouchMode
属性を true
に設定する。このステップが必要なのは、
一部のテレビデバイスでは、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)
)
)
}
}
Java
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);
}
});
スライダーのサポートを追加する
テレビの TalkBack は、スライダーに特別な対応を行っています。スライダー モードを有効にするには、
RangeInfo
オブジェクトとともにビューに ACTION_SET_PROGRESS
を追加します。
ユーザーがテレビのリモコンの中央ボタンを押してスライダー モードに入ります。
このモードでは、矢印ボタンで 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;
}
}
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-07-27 UTC。
[null,null,["最終更新日 2025-07-27 UTC。"],[],[],null,["# Support TalkBack in TV apps\n\nTV apps sometimes have use cases that make it difficult for users who rely on\n[TalkBack](/guide/topics/ui/accessibility/testing#talkback) to use the app. To provide a better TalkBack experience for these\nusers, review each of the sections in this guide and implement changes in your\napp where necessary. If your app uses custom views, you should also refer to the\n[corresponding guide](/training/tv/accessibility/custom-views) that describes how to support accessibility with custom\nviews.\n\nHandle nested views\n-------------------\n\nNested views can be hard for TalkBack users to navigate. Whenever possible, make\neither the parent or the child view focusable by TalkBack, but not both.\n\nTo make a view focusable by TalkBack, set the [`focusable`](/reference/android/view/View#attr_android:focusable) and the\n[`focusableInTouchMode`](/reference/android/view/View#attr_android:focusableInTouchMode) attribute to `true`. This step is necessary because\nsome TV devices might enter and exit touch mode while TalkBack is active.\n\nTo make a view non-focusable, it is sufficient to set the [`focusable`](/reference/android/view/View#attr_android:focusable)\nattribute to `false`. However, if the view is actionable (that is, its\ncorresponding `AccessibilityNodeInfo` has [`ACTION_CLICK`](/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_CLICK)), it might still\nbe focusable.\n\nChange descriptions for Actions\n-------------------------------\n\nBy default, TalkBack announces \"Press select to activate\" for actionable views.\nFor some actions, the term \"activate\" might not be a good description. To\nprovide a more accurate description, you can change it: \n\n### Kotlin\n\n```kotlin\nfindViewById\u003cView\u003e(R.id.custom_actionable_view).accessibilityDelegate = object : View.AccessibilityDelegate() {\n override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {\n super.onInitializeAccessibilityNodeInfo(host, info)\n info.addAction(\n AccessibilityAction(\n AccessibilityAction.ACTION_CLICK.id,\n getString(R.string.custom_label)\n )\n )\n }\n}\n```\n\n### Java\n\n```java\nfindViewById(R.id.custom_actionable_view).setAccessibilityDelegate(new AccessibilityDelegate() {\n @Override\n public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {\n super.onInitializeAccessibilityNodeInfo(host, info);\n AccessibilityAction action = new AccessibilityAction(\n AccessibilityAction.ACTION_CLICK.getId(), getString(R.string.custom_label));\n info.addAction(action);\n }\n});\n```\n\nAdd support for sliders\n-----------------------\n\nTalkBack on TV has special support for sliders. To enable slider mode, add\n[`ACTION_SET_PROGRESS`](/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_SET_PROGRESS) to a view together with a [`RangeInfo`](/reference/android/view/accessibility/AccessibilityNodeInfo.RangeInfo) object.\n\nThe user enters the slider mode by pressing the center button of the TV remote.\nIn this mode, the arrow buttons generate [`ACTION_SCROLL_FORWARD`](/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_FORWARD) and\n[`ACTION_SCROLL_BACKWARD`](/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_BACKWARD) accessibility actions.\n\nThe following example implements a volume slider with levels from 1 to 10: \n\n### Kotlin\n\n```kotlin\n/**\n * This example only provides slider functionality for TalkBack users. Additional logic should\n * be added for other users. Such logic may reuse the increase and decrease methods.\n */\nclass VolumeSlider(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {\n private val min = 1\n private val max = 10\n private var current = 5\n private var textView: TextView? = null\n\n init {\n isFocusable = true\n isFocusableInTouchMode = true\n val rangeInfo =\n AccessibilityNodeInfo.RangeInfo(\n AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_INT,\n min.toFloat(),\n max.toFloat(),\n current.toFloat()\n )\n accessibilityDelegate =\n object : AccessibilityDelegate() {\n override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {\n super.onInitializeAccessibilityNodeInfo(host, info)\n info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_PROGRESS)\n info.rangeInfo = rangeInfo\n }\n\n override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean {\n if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.id) {\n increase()\n return true\n }\n if (action == AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD.id) {\n decrease()\n return true\n }\n return super.performAccessibilityAction(host, action, args)\n }\n }\n }\n\n override fun onFinishInflate() {\n super.onFinishInflate()\n textView = findViewById(R.id.text)\n textView!!.text = context.getString(R.string.level, current)\n }\n\n private fun increase() {\n update((current + 1).coerceAtMost(max))\n }\n\n private fun decrease() {\n update((current - 1).coerceAtLeast(min))\n }\n\n private fun update(newLevel: Int) {\n if (textView == null) {\n return\n }\n val newText = context.getString(R.string.level, newLevel)\n // Update the user interface with the new volume.\n textView!!.text = newText\n // Announce the new volume.\n announceForAccessibility(newText)\n current = newLevel\n }\n}\n```\n\n### Java\n\n```java\n/**\n * This example only provides slider functionality for TalkBack users. Additional logic should\n * be added for other users. Such logic can reuse the increase and decrease methods.\n */\npublic class VolumeSlider extends LinearLayout {\n private final int min = 1;\n private final int max = 10;\n private int current = 5;\n private TextView textView;\n\n public VolumeSlider(Context context, AttributeSet attrs) {\n super(context, attrs);\n setFocusable(true);\n setFocusableInTouchMode(true);\n RangeInfo rangeInfo = new RangeInfo(RangeInfo.RANGE_TYPE_INT, min, max, current);\n setAccessibilityDelegate(\n new AccessibilityDelegate() {\n @Override\n public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {\n super.onInitializeAccessibilityNodeInfo(host, info);\n info.addAction(AccessibilityAction.ACTION_SET_PROGRESS);\n info.setRangeInfo(rangeInfo);\n }\n\n @Override\n public boolean performAccessibilityAction(View host, int action, Bundle args) {\n if (action == AccessibilityAction.ACTION_SCROLL_FORWARD.getId()) {\n increase();\n return true;\n }\n if (action == AccessibilityAction.ACTION_SCROLL_BACKWARD.getId()) {\n decrease();\n return true;\n }\n return super.performAccessibilityAction(host, action, args);\n }\n });\n }\n\n @Override\n protected void onFinishInflate() {\n super.onFinishInflate();\n textView = findViewById(R.id.text);\n textView.setText(getContext().getString(R.string.level, current));\n }\n\n private void increase() {\n update(Math.min(current + 1, max));\n }\n\n private void decrease() {\n update(Math.max(current - 1, min));\n }\n\n private void update(int newLevel) {\n if (textView == null) {\n return;\n }\n String newText = getContext().getString(R.string.level, newLevel);\n // Update the user interface with the new volume.\n textView.setText(newText);\n // Announce the new volume.\n announceForAccessibility(newText);\n current = newLevel;\n }\n}\n```"]]