Supporto di TalkBack nelle app per TV

A volte le app TV presentano casi d'uso che rendono difficile per gli utenti che fanno affidamento su TalkBack per utilizzare l'app. Per offrire una migliore esperienza di TalkBack per questi gli utenti, esamina ciascuna sezione di questa guida e implementa le modifiche nel tuo ove necessario. Se la tua app utilizza le visualizzazioni personalizzate, devi fare riferimento anche alle guida corrispondente che descrive come supportare l'accessibilità con visualizzazioni.

Gestire le visualizzazioni nidificate

Le visualizzazioni nidificate possono essere difficoltose per gli utenti di TalkBack. Se possibile, esegui la vista principale o quella secondaria attivabile da TalkBack, ma non entrambe.

Per rendere una visualizzazione attivabile da TalkBack, imposta focusable e focusableInTouchMode a true. Questo passaggio è necessario perché alcuni dispositivi TV potrebbero entrare e uscire dalla modalità touch mentre TalkBack è attivo.

Per rendere una visualizzazione non attivabile, è sufficiente impostare la focusable. a false. Tuttavia, se la visualizzazione è strategica (ovvero, AccessibilityNodeInfo corrispondente ha ACTION_CLICK), potrebbe comunque attivabile.

Modificare le descrizioni delle azioni

Per impostazione predefinita, TalkBack pronuncia il comando "Premi Seleziona per attivare" per ottenere informazioni strategiche. Per alcune azioni, il termine "attivare" potrebbe non essere una buona descrizione. A fornire una descrizione più accurata, puoi modificarla:

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

Aggiungere il supporto per i cursori

TalkBack sulla TV supporta i cursori in modo speciale. Per attivare la modalità di scorrimento, aggiungi ACTION_SET_PROGRESS a una vista insieme a un oggetto RangeInfo.

L'utente accede alla modalità del dispositivo di scorrimento premendo il pulsante centrale del telecomando della TV. In questa modalità, i pulsanti freccia generano ACTION_SCROLL_FORWARD e ACTION_SCROLL_BACKWARD azioni di accessibilità.

L'esempio seguente implementa un cursore del volume con livelli da 1 a 10:

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