پشتیبانی از TalkBack در برنامه‌های تلویزیون

برنامه‌های تلویزیون گاهی اوقات موارد استفاده‌ای دارند که استفاده از برنامه را برای کاربرانی که به TalkBack متکی هستند دشوار می‌کند. برای ارائه تجربه TalkBack بهتر برای این کاربران، هریک از بخش‌های این راهنما را مرور کنید و درصورت لزوم تغییراتی در برنامه‌تان اعمال کنید. اگر برنامه‌تان از نماهای سفارشی استفاده می‌کند، باید به راهنمای مربوطه که نحوه پشتیبانی از دسترس‌پذیری با نماهای سفارشی را شرح می‌دهد مراجعه کنید.

مدیریت نماهای تودرتو

پیمایش نماهای تودرتو می‌تواند برای کاربران TalkBack دشوار باشد. هرزمان ممکن بود، نمای والد یا فرزند را برای TalkBack قابل‌تمرکز کنید، اما نه هر دو را.

برای اینکه TalkBack بتواند روی نمایی تمرکز کند، focusable و مشخصه focusableInTouchMode را روی true تنظیم کنید. این مرحله ضروری است زیرا برخی‌از دستگاه‌های تلویزیون ممکن است هنگام فعال بودن TalkBack وارد حالت لمسی شوند و از آن خارج شوند.

برای غیرقابل‌تمرکز کردن یک نما، کافی است مشخصه focusable را روی false تنظیم کنید. بااین‌حال، اگر نما قابل‌کنش باشد (یعنی AccessibilityNodeInfo مربوطه آن دارای ACTION_CLICK باشد)، ممکن است همچنان قابل‌تمرکز باشد.

تغییر شرح «کنش‌ها»

به‌طور پیش‌فرض، TalkBack برای نماهای کنش‌پذیر «برای فعال کردن، انتخاب را فشار دهید» را اعلام می‌کند. برای برخی‌از کنش‌ها، عبارت «فعال کردن» ممکن است توصیف خوبی نباشد. برای ارائه شرح دقیق‌تر، می‌توانید آن را تغییر دهید:

کاتلین

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

افزودن پشتیبانی از لغزنده‌ها

‫TalkBack در تلویزیون پشتیبانی ویژه‌ای از لغزنده‌ها دارد. برای فعال کردن حالت لغزنده، ACTION_SET_PROGRESS را همراه با شیء RangeInfo به نما اضافه کنید.

کاربر با فشار دادن دکمه مرکزی کنترل از راه دور تلویزیون وارد حالت لغزنده می‌شود. در این حالت، دکمه‌های جهت‌نما کنش‌های دسترس‌پذیری ACTION_SCROLL_FORWARD و ACTION_SCROLL_BACKWARD را ایجاد می‌کنند.

مثال زیر لغزنده میزان صدا را با سطوح ۱ تا ۱۰ پیاده‌سازی می‌کند:

کاتلین

/**
 *   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
  }
}

جاوا

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