J'essaie de savoir ce qui se passe exactement différemment lors de la publication d'un UIAccessibilityLayoutChangedNotification
et d'un UIAccessibilityScreenChangedNotification
. D'après ce que je peux voir, je peux les utiliser de manière interchangeable partout et rien de différent ne se produit.
La documentation Apple Apple dit simplement d'utiliser LayoutChanged
quand (par exemple) un élément a été masqué ou affiché, et d'utiliser ScreenChanged
si tout l'écran change, mais je suis intéressé par ce qu'ils font quand je fournis ces informations, et ce que je dois voir différemment lorsque j'utilise l'un ou l'autre.
Quelqu'un peut-il expliquer clairement les différences de mise en œuvre entre les deux?
Ces deux notifications concernent le contenu dynamique des vues et communiquent ces modifications à VoiceOver pour les utilisateurs de lecteurs d'écran. Il y a peu de différence entre ces deux notifications, à l'exception de leur comportement par défaut, et le petit "bip bip" idiot pour les notifications ScreenChange.
Dans les deux cas, l'argument
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, arg);
Représente une chaîne à lire ou un élément à l'écran vers lequel VoiceOver déplacera son focus. En cas de changements de contexte dramatiques, il est important d'envoyer le focus à un endroit qui a du sens, ou d'annoncer que de tels changements ont eu lieu. L'une ou l'autre approche est acceptable du point de vue de l'accessibilité, bien que je préfère les approches qui impliquent le moins de changement possible. Dans le cas de simples changements de mise en page, il est presque toujours préférable d'annoncer le changement de contexte et de laisser le focus où il était. Bien que parfois, l'élément qui a provoqué le changement de contexte soit masqué, et il est alors clairement nécessaire de diriger la voix off pour mettre en évidence le nouveau contenu, car le comportement par défaut dans ce cas n'est pas défini, ou peut-être déterministe, mais déterminé par un cadre qui ne sait absolument rien à propos de votre application!
La différence entre les deux événements, étant donné qu'ils font tous deux exactement la même chose, réside dans leur comportement par défaut. Si vous fournissez nil au UIAccessibilityLayoutChangedNotification
, c'est comme si vous n'aviez rien fait. Si vous fournissez un argument nil au UIAccessibilityScreenChangedNotification
, il enverra le focus au premier UIObject de votre hiérarchie de vues qui est marqué comme un élément d'accessibilité, une fois que tous les changements de hiérarchie de vues et les dessins sont terminés.
UIAccessibilityLayoutChangedNotification
Un bon exemple de cas d'utilisation pour UIAccessibilityLayoutChangedNotification
concerne les formulaires dynamiques. Vous souhaitez informer les utilisateurs que, en fonction des décisions qu'ils ont prises dans le formulaire, de nouvelles options sont disponibles. Par exemple, si dans un formulaire vous sélectionnez que vous êtes un ancien combattant, des zones supplémentaires du formulaire peuvent apparaître pour fournir plus de commentaires, mais ces zones peuvent avoir été masquées par d'autres utilisateurs qui ne se souciaient pas d'eux. Vous pouvez donc déplacer le focus sur ces éléments après l'interaction avec l'utilisateur:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, firstNewFormElement);
Ce qui déplacerait le focus sur l'élément fourni et annoncerait son accessibilitéLabel.
Ou dites-leur simplement que les nouveaux éléments du formulaire sont là:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, @"Veterans form elements available");
Ce qui laisserait le focus là où il se trouve, mais VoiceOver annoncerait "des éléments de forme de vétérans disponibles".
Remarque: Ce comportement particulier est buggé sur mon iPad (8.1.2).
Ou enfin, vous pouvez le faire:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
Ce qui ne fait absolument rien :). Sérieusement, je ne pense même pas que le backend du framework a11y s'en soucie. Cette ligne de code particulière est un gaspillage complet!
UIAccessibilityScreenChangedNotification
Un bon exemple de cas d'utilisation pour UIAccessibilityScreenChangedNotification
est les situations de navigation par onglets personnalisées. Lorsque tout l'écran, à l'exception de votre zone de navigation, change. Vous voulez faire savoir à la voix off que la totalité de l'écran a changé, mais PAS pour focaliser le premier élément (votre premier onglet) mais pour focaliser le premier élément de contenu.
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstNonGlobalNavElement);
Qui jouerait le son "boop beep" et déplacerait ensuite le focus juste sous votre barre de navigation globale. Ou vous pouvez le faire:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"You're on a new tab");
Qui attendrait que le nouvel onglet se charge, joue le son "beep boop", annonce "Vous êtes sur un nouvel onglet" en voix off, puis déplace le focus sur le premier élément de l'écran, puis annonce le label d'accessibilité pour cet élément. (PHEW! C'est beaucoup! C'est choquant pour les utilisateurs de lecteurs d'écran. Évitez ce scénario, sauf si absolument nécessaire).
Et enfin, vous pouvez bien sûr faire ceci:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
Ce qui équivaut à:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstA11yElement);
Les deux émettront le son "bip sonore", décaleront la mise au point VoiceOver sur le premier élément de l'écran, puis l'annonceront.
Enfin
Dans un commentaire, quelqu'un a mentionné la mise en cache, et je commente parfois dans ma réponse des choses dont le backend A11y peut ou non se soucier. Bien qu'il soit certainement possible qu'il y ait de la magie de back-end, je ne crois en aucune de ces circonstances, le back-end se soucie du tout. La raison pour laquelle je dis cela est parce que:
Si vous avez déjà utilisé le protocole UIAccessibilityContainer
, vous pouvez regarder pendant que votre conteneur de vues est interrogé. Il n'y a pas de mise en cache. Même la propriété accessibilityElementCount
reçoit un ping à chaque fois que VoiceOver change de focus vers un nouvel AccessibilityElement dans votre conteneur. Ensuite, il passe par le processus de vérification de l'élément sur lequel il se trouve, demande l'élément suivant, etc. Il est conçu à la base pour gérer des situations dynamiques. Si vous deviez insérer un nouvel élément dans votre conteneur après l'interaction, il passerait toujours par toutes ces requêtes et irait très bien! De plus, si vous remplacez les propriétés du protocole UIAccessibility, afin de fournir des conseils et des étiquettes dynamiques, vous pouvez également voir que ces fonctions sont appelées à chaque fois! En tant que tel, je pense que le backend A11y Framework glane des informations ABSOLUMENT ZÉRO dans ces notifications. La seule information dont VoiceOver a besoin pour faire son travail est qu'il est actuellement focalisé sur l'élément d'accessibilité, et sur ces éléments le conteneur d'accessibilité. Les notifications sont simplement là pour que vous puissiez rendre votre application plus utilisable pour les utilisateurs de VoiceOver.
Imaginez si ce n'était pas le cas combien de fois Safari publierait ces notifications !!!! :)
Ces déclarations particulières ne peuvent être confirmées que par une personne ayant des connaissances en arrière-plan du cadre, qui travaille avec le code, et doivent être considérées comme des conjectures. Il se peut que cela dépende fortement de la version/de l'implémentation. Certainement ouvert à la discussion sur ces points! Le reste de ce post est assez concret.
Pour votre référence
La plupart de cela provient de l'expérience de travail avec les frameworks, mais voici une référence utile si vous souhaitez creuser davantage.
https://developer.Apple.com/documentation/uikit/accessibility/uiaccessibility
https://developer.Apple.com/documentation/uikit/uiaccessibilitylayoutchangednotification
https://developer.Apple.com/documentation/uikit/uiaccessibilityscreenchangednotification
Et enfin, un repo open source de la petite application idiote que j'ai mis en place pour tester tout ça.