TV uygulamalarında TalkBack'i destekleme

TV uygulamalarında bazen TalkBack'i kullananların uygulamayı kullanmasını zorlaştıran kullanım alanları bulunur. Bu kullanıcılara daha iyi bir TalkBack deneyimi sunmak için bu rehberdeki her bölümü inceleyin ve uygulamanızda gerekli değişiklikleri yapın. Uygulamanızda özel görünümler kullanılıyorsa özel görünümlerle erişilebilirliği destekleme yöntemlerini açıklayan ilgili kılavuza da göz atmanız gerekir.

İç içe yerleştirilmiş görünümleri işleme

İç içe geçmiş görünümlerde TalkBack kullanıcılarının gezinmesi zor olabilir. Mümkün olduğunda, hem ebeveyn hem de çocuk ekranı görünümünü değil, yalnızca birini TalkBack ile odaklanılabilir hale getirin.

Bir görünümün TalkBack tarafından odaklanılabilir hale getirilmesi için focusable ve focusableInTouchMode özelliklerini true olarak ayarlayın. Bu adım, TalkBack etkinken bazı TV cihazlarının dokunma moduna girip çıkabilmesi nedeniyle gereklidir.

Bir görünümü odaklanılamaz hale getirmek için focusable özelliğini false olarak ayarlamak yeterlidir. Ancak görünümde işlem yapılabiliyorsa (yani ilgili AccessibilityNodeInfo öğesinde ACTION_CLICK varsa) görünüm yine de odaklanılabilir.

İşlemlerin açıklamalarını değiştirme

TalkBack, varsayılan olarak işlem yapılabilir görünümler için "Etkinleştirmek için seçme düğmesine basın" ifadesini okur. Bazı işlemler için "etkinleştir" terimi iyi bir açıklama olmayabilir. Daha doğru bir açıklama sağlamak için açıklamayı değiştirebilirsiniz:

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

Kaydırma çubukları için destek ekleme

TV'de TalkBack, kaydırma çubukları için özel destek sunar. Kaydırma çubuğu modunu etkinleştirmek için bir görünüme RangeInfo nesnesiyle birlikte ACTION_SET_PROGRESS ekleyin.

Kullanıcı, TV uzaktan kumandasının ortadaki düğmesine basarak kaydırma moduna girer. Bu modda ok düğmeleri ACTION_SCROLL_FORWARD ve ACTION_SCROLL_BACKWARD erişilebilirlik işlemlerini oluşturur.

Aşağıdaki örnekte, 1 ile 10 arasında seviyeleri olan bir ses kaydırma çubuğu uygulanmaktadır:

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