TalkBack in TV-Apps unterstützen

Für TV-Apps gibt es manchmal Anwendungsfälle, die es Nutzern schwer machen, TalkBack zum Verwenden der App. Um eine bessere TalkBack-Nutzung für diese lesen Sie die einzelnen Abschnitte in diesem Leitfaden und nehmen Sie Änderungen an Ihrem bei Bedarf die App herunter. Wenn Ihre App benutzerdefinierte Ansichten verwendet, sollten Sie auch die entsprechenden Leitfaden, in dem beschrieben wird, wie Sie mit benutzerdefinierten Aufrufe.

Verschachtelte Ansichten verarbeiten

Die Navigation in verschachtelten Ansichten kann für TalkBack-Nutzer schwierig sein. Stellen Sie nach Möglichkeit die über TalkBack fokussierbar sind, aber nicht beide.

Um eine Ansicht von TalkBack fokussierbar zu machen, legen Sie focusable und die focusableInTouchMode-Attribut zu true. Dieser Schritt ist notwendig, Auf einigen Fernsehern wird möglicherweise der Touchmodus aktiviert und beendet, wenn TalkBack aktiv ist.

Um eine Ansicht nicht fokussierbar zu machen, reicht es aus, den Parameter focusable festzulegen. Attribut zu false. Wenn die Ansicht jedoch entscheidungsrelevant ist (d. h. entsprechende AccessibilityNodeInfo den Wert ACTION_CLICK hat, wird er möglicherweise trotzdem fokussierbar sein.

Beschreibungen für Aktionen ändern

Standardmäßig sagt TalkBack „Zum Aktivieren Auswahl drücken“ an. um umsetzbare Ansichten zu erhalten. Bei einigen Aktionen hat der Begriff „aktivieren“ ist vielleicht keine gute Beschreibung. Bis genauere Beschreibung angeben, können Sie diese ändern:

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);
  }
});

Unterstützung für Schieberegler hinzufügen

TalkBack auf Fernsehern bietet eine spezielle Unterstützung für Schieberegler. Um den Slider-Modus zu aktivieren, fügen Sie ACTION_SET_PROGRESS zu einer Ansicht zusammen mit einem RangeInfo-Objekt.

Der Nutzer wechselt durch Drücken der mittleren Taste auf der Fernbedienung des Fernsehers zum Schiebereglermodus. In diesem Modus generieren die Pfeiltasten ACTION_SCROLL_FORWARD und ACTION_SCROLL_BACKWARD Aktionen für Bedienungshilfen.

Im folgenden Beispiel wird ein Lautstärkeregler mit Stufen von 1 bis 10 implementiert:

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;
  }
}