إتاحة ميزة TalkBack في تطبيقات التلفزيون

في بعض الأحيان، تتضمّن تطبيقات التلفزيون حالات استخدام تجعل من الصعب على المستخدمين الذين يعتمدون على 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;
  }
}