Эти два уведомления предназначены для динамического содержимого в представлениях и для передачи этих изменений в VoiceOver для пользователей программ чтения с экрана. Между этими двумя уведомлениями нет большой разницы, за исключением их поведения по умолчанию и глупого маленького «гудка» для уведомлений об изменении экрана.
В обоих случаях аргумент
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, arg);
Представляет строку для чтения или элемент на экране, на который VoiceOver переместит фокус. В случае резкого изменения контекста важно направить внимание на то место, которое имеет смысл, или объявить, что такие изменения произошли. Любой подход приемлем с точки зрения доступности, хотя я предпочитаю подходы, предполагающие наименьшее количество возможных изменений. В случае простых изменений макета почти всегда лучше просто объявить об изменении контекста и оставить фокус там, где он был. Хотя иногда элемент, вызвавший изменение контекста, скрывается, и тогда явно необходимо направлять озвучку для выделения нового контента, потому что поведение по умолчанию в этом случае не определено, а может, и детерминировано, но определяется фреймворком, который абсолютно ничего не знает. о вашем приложении!
Разница между двумя событиями, учитывая, что они оба делают одно и то же, заключается в их поведении по умолчанию. Если вы поставите nil в UIAccessibilityLayoutChangedNotification
, это как если бы вы ничего не сделали. Если вы укажете нулевой аргумент для UIAccessibilityScreenChangedNotification
, он отправит фокус на первый UIObject в вашей иерархии представлений, который помечен как accessibilityElement, как только все изменения иерархии представлений и рисунки будут завершены.
UIAccessibilityLayoutChangedNotification
Хороший пример использования UIAccessibilityLayoutChangedNotification
для динамических форм. Вы хотите, чтобы пользователи знали, что в зависимости от решений, которые они приняли в форме, доступны новые параметры. Например, если в форме вы укажете, что являетесь ветераном, могут появиться дополнительные области формы для ввода дополнительных данных, но эти области могут быть скрыты для других пользователей, которым они не нужны. Таким образом, вы можете сместить фокус на эти элементы после взаимодействия с пользователем:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, firstNewFormElement);
Что сместит фокус на предоставленный элемент и объявит его accessibilityLabel.
Или просто скажите им, что появились новые элементы формы:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, @"Veterans form elements available");
Это оставило бы фокус там, где он есть, но VoiceOver объявил бы «Доступны элементы формы ветеранов».
Примечание. Это конкретное поведение вызывает ошибку на моем iPad (8.1.2).
Или, наконец, вы могли бы сделать это:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
Который абсолютно ничего не делает :). Серьезно, я даже не думаю, что бэкэнд a11y framework заботится. Эта конкретная строка кода — полная трата!
UIAccessibilityScreenChangedNotification
Хорошим примером использования UIAccessibilityScreenChangedNotification
являются настраиваемые ситуации просмотра вкладок. Когда меняется весь экран, за исключением области навигации. Вы хотите, чтобы голос за кадром знал, что по существу изменился весь экран, но НЕ для того, чтобы сфокусироваться на первом элементе (ваша первая вкладка), а чтобы сфокусироваться на первом элементе контента.
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstNonGlobalNavElement);
Который воспроизведет звук «бип», а затем переместит фокус прямо под вашу глобальную панель навигации. Или вы можете сделать это:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"You're on a new tab");
Который будет ждать загрузки новой вкладки, воспроизводить звук «бип-буп», объявлять «Вы находитесь на новой вкладке» в голосе за кадром, затем перемещать фокус на первый элемент на экране, а затем объявлять accessibilityLabel для этого элемента. (ФУУУ! Это много! Это раздражает пользователей программ чтения с экрана. Избегайте этого сценария, если в этом нет крайней необходимости).
И, наконец, вы, конечно, можете сделать это:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
Что эквивалентно:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstA11yElement);
Оба из них будут воспроизводить звук «бип-буп», переключать фокус VoiceOver на первый элемент на экране, а затем объявлять об этом.
Наконец-то
В комментарии кто-то упомянул кэширование, и я иногда комментирую в своем ответе вещи, которые могут или не могут быть важны для A11y Backend. Хотя вполне возможно, что происходит какое-то волшебство бэкэнда, я не верю ни в одно из этих обстоятельств, бэкенду вообще все равно. Я говорю это потому, что:
Если вы когда-либо использовали протокол UIAccessibilityContainer
, вы можете наблюдать, как запрашивается ваш контейнер представлений. Кэширование не происходит. Даже свойство accessibilityElementCount
проверяется каждый раз, когда VoiceOver изменяет фокус на новый AccessibilityElement в вашем контейнере. Затем он проходит процесс проверки того, на каком элементе он находится, запрашивает следующий элемент и так далее. Он разработан по своей сути для обработки динамических ситуаций. Если бы вы вставили новый элемент в свой контейнер после взаимодействия, он все равно прошел бы все эти запросы и был бы в порядке! Кроме того, если вы переопределите свойства протокола UIAccessibility для предоставления динамических подсказок и меток, вы также увидите, что эти функции вызываются каждый раз! Таким образом, я считаю, что серверная часть A11y Framework собирает АБСОЛЮТНО НУЛЕВУЮ информацию из этих уведомлений. Единственная информация, необходимая VoiceOver для выполнения своей работы, — это элемент специальных возможностей, сфокусированный в данный момент, и контейнер специальных возможностей этого элемента. Уведомления просто нужны вам, чтобы сделать ваше приложение более удобным для пользователей VoiceOver.
Представьте, если бы это было не так, сколько раз Safari публиковал бы эти уведомления!!!! :)
Эти конкретные утверждения могут быть подтверждены только кем-то, кто хорошо разбирается в инфраструктуре, кто работает с кодом, и их следует рассматривать как предположения. Возможно, это сильно зависит от версии/реализации. Определенно открыт для обсуждения этих вопросов! Остальная часть этого поста довольно конкретна.
Для справки
Большая часть этого исходит из опыта работы с фреймворками, но вот полезная ссылка, если вы хотите копнуть дальше.
https://developer.apple.com/documentation/uikit/accessibility/uiaccessibility
https://developer.apple.com/documentation/uikit/uiaccessibilitylayoutchangednotification
https://developer.apple.com/documentation/uikit/uiaccessibilityscreenchangednotification
И, наконец, репозиторий с открытым исходным кодом глупого маленького приложения, которое я собрал, чтобы протестировать все это.
https://github.com/chriscm2006/IOS-A11y-Api-Test
person
ChrisCM
schedule
05.02.2015