Иногда в ТВ-приложениях есть функции, которые затрудняют их использование с помощью 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 на телевизоре поддерживает ползунки. Чтобы включить режим ползунка, добавьте в представление объект ACTION_SET_PROGRESS вместе с объектом RangeInfo.
Чтобы перейти в режим ползунка, пользователь нажимает центральную кнопку на пульте телевизора.
В этом режиме кнопки со стрелками генерируют действия специальных возможностей 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;
}
}