รองรับ TalkBack ในแอปทีวี

บางครั้งแอปทีวีก็มีกรณีการใช้งานที่ทำให้ผู้ใช้ที่ต้องพึ่งพา TalkBack ใช้งานแอปได้ยาก โปรดอ่านแต่ละส่วนในคู่มือนี้และทำการเปลี่ยนแปลงใน แอปตามความจำเป็นเพื่อให้ผู้ใช้ เหล่านี้ได้รับประสบการณ์การใช้งาน TalkBack ที่ดียิ่งขึ้น หากแอปใช้มุมมองที่กำหนดเอง คุณควรดูคู่มือที่เกี่ยวข้องที่ อธิบายวิธีรองรับการช่วยเหลือพิเศษด้วยมุมมองที่กำหนดเองด้วย

จัดการมุมมองที่ซ้อนกัน

มุมมองที่ซ้อนกันอาจทำให้ผู้ใช้ TalkBack ใช้งานได้ยาก ให้กำหนดให้มุมมองระดับบนหรือหน้าจอสำหรับเด็กอย่างใดอย่างหนึ่งสามารถโฟกัสได้ด้วย TalkBack แต่ไม่ใช่ทั้ง 2 อย่าง หากเป็นไปได้

หากต้องการให้ 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;
  }
}