Подтвердить что ты не робот

Фактическая разница между UIAccessibilityLayoutChangedNotification и UIAccessibilityScreenChangedNotification?

Я пытаюсь выяснить, что именно происходит при публикации UIAccessibilityLayoutChangedNotification и UIAccessibilityScreenChangedNotification. Из того, что я вижу, я могу использовать их взаимозаменяемо везде и ничего не происходит.

Документация Apple просто говорит использовать LayoutChanged, когда (например) элемент был скрыт или показан, и использовать ScreenChanged, если весь экран меняется, но Im заинтересован в том, что они делают, когда я предоставляю эту информацию, и что я должен видеть по-другому при использовании того или другого.

Может ли кто-нибудь дать четкое объяснение различий в реализации между этими двумя?

4b9b3361

Ответ 1

Эти два уведомления относятся к динамическому контенту на представлениях и сообщают об этих изменениях в VoiceOver для пользователей экранных прошивок. Существует мало различий между этими двумя уведомлениями, за исключением их поведения по умолчанию, и глупый маленький "звуковой сигнал" для уведомлений ScreenChange.

В обоих случаях аргумент

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, arg);

Представляет строку для считывания или элемент на экране, на который VoiceOver переключит свой фокус. В случае резких изменений контекста важно отправить фокус на место, которое имеет смысл, или объявить, что такие изменения произошли. Любой подход приемлем с точки зрения доступности, хотя я предпочитаю подходы, которые предполагают наименьшее количество возможных изменений. В случае простых изменений компоновки почти всегда лучше всего объявить об изменении контекста и оставить фокус там, где он был. Хотя иногда элемент, вызвавший изменение контекста, скрыт, и тогда, очевидно, необходимо прямое озвучивание, чтобы выделить новый контент, потому что поведение по умолчанию в этом случае undefined или, возможно, детерминированное, но определяется каркасом, который знает абсолютно ничего о вашем приложении!

Различие между двумя событиями, учитывая, что они оба делают точно то же самое, находится в их поведении по умолчанию. Если вы подаете нуль в UIAccessibilityLayoutChangedNotification, то как будто вы ничего не сделали. Если вы предоставите аргумент nil для UIAccessibilityScreenChangedNotification, он отправит фокус в первый UIObject в иерархии вашего представления, который будет помечен как элемент accessibilityElement, после того, как все изменения иерархии представлений и чертежи будут завершены.

UIAccessibilityLayoutChangedNotification

Хороший пример использования для UIAccessibilityLayoutChangedNotification предназначен для динамических форм. Вы хотите сообщить пользователям, что на основе решений, которые они приняли в форме, доступны новые параметры. Например, если в форме вы выбираете, что вы являетесь ветераном, дополнительные области формы могут появляться, чтобы обеспечить больше ввода, но эти области, возможно, были скрыты для других пользователей, которые не заботились о них. Таким образом, вы можете переключать фокус на эти элементы после взаимодействия с пользователем:

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, firstNewFormElement);

Что бы переключить фокус на предоставленный элемент и объявить его accessibilityLabel.

Или просто скажите им, что есть новые элементы формы:

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, @"Veterans form elements available");

Что бы оставить фокус там, где он есть, но VoiceOver объявит "Элементы формы ветеранов".

Примечание. Это особое поведение прослушивается на моем iPad (8.1.2).

Или, наконец, вы можете сделать это:

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);

Что абсолютно ничего:). Серьезно, я даже не думаю, что бэкэнд a11y заботится. Эта конкретная строка кода представляет собой полный отход!

UIAccessibilityScreenChangedNotification

Хорошим примером использования для UIAccessibilityScreenChangedNotification является настраиваемый режим просмотра с вкладками. Когда изменяется весь экран, за исключением области навигации, изменяется. Вы хотите, чтобы озвучивание знало, что по существу весь экран изменился, но НЕ сфокусировать первый элемент (первую вкладку), а сосредоточить первый элемент содержимого.

UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstNonGlobalNavElement);

который будет воспроизводить звук звукового сигнала "boop beep", а затем переключить фокус только под вашу глобальную навигационную панель. Или вы можете сделать это:

UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"You're on a new tab");

Что будет ждать загрузки новой вкладки, воспроизведения звука "звуковой сигнал" , анонса "Вы на новой вкладке" в озвучке, затем смените фокус на первый элемент на экране, а затем объявите accessibilityLabel для этот элемент. (PHEW! Это много! Это раздражает пользователей экрана. Избегайте этого сценария, если это абсолютно необходимо).

И, наконец, вы, конечно, можете это сделать:

UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);    

Что эквивалентно:

UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstA11yElement);

Оба из них будут воспроизводить звук "звуковой сигнал" , сдвигают фокусировку VoiceOver на первый элемент на экране, а затем объявляют об этом.

Наконец

В комментарии кто-то упомянул о кешировании, и я иногда комментирую в своем ответе о вещах, которые могут или не могут волновать A11y Backend. Хотя, конечно, возможно, что есть какая-то бэкэнд-магия, я не верю ни в одно из этих обстоятельств, задняя часть вообще не волнует. Причина, по которой я говорю это, заключается в следующем:

Если вы когда-либо использовали протокол UIAccessibilityContainer, вы можете наблюдать, как запрашивается ваш контейнер просмотров. Кэширования не происходит. Даже свойство accessibilityElementCount получает pinged каждый раз, когда VoiceOver меняет фокус на новый AccessibilityElement в вашем контейнере. Затем он проходит процесс проверки, на каком элементе он находится, запрашивает следующий элемент и т.д. Он сконструирован в своей основе для обработки динамических ситуаций. Если бы вы вставляли новый элемент в свой контейнер после взаимодействия, он все равно просматривал все эти запросы и был бы в порядке! Кроме того, если вы переопределите свойства протокола UIAccessibility, чтобы предоставить динамические подсказки и метки, вы также можете увидеть, что эти функции вызываются каждый раз! Как таковой, я считаю, что бэкэнд A11y Framework отображает информацию ABSOLUTELY ZERO из этих уведомлений. Единственная информация, которую VoiceOver должна выполнять, заключается в том, что в данный момент она сосредоточена на элементе доступности, а также на элементах Accessibility Container. Уведомления просто предназначены для того, чтобы ваше приложение стало более удобным для пользователей 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

Ответ 2

UIAccessibilityScreenChangedNotification означает, что весь экран изменился, а VoiceOver должен reset.

UIAccessibilityLayoutChangedNotification означает, что один или несколько, но не все элементы на экране изменились.

когда ваш пользовательский интерфейс сильно изменится. Обычно, когда пользователь перемещается в другую часть вашего приложения (переходит на другой экран). VoiceOver уведомляет пользователя с тональным сигналом, и он очищает свои кэши и выполняет другие подготовительные операции для обработки нового набора данных доступности. Он предупреждает VoiceOver о том, что экран изменился, и на экране могут появиться новые элементы, поэтому VoiceOver перестроит его индекс элементов доступности.

UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);

Если какая-то часть вашего пользовательского интерфейса изменяется, но пользователь не обязательно прыгнул в совершенно другую часть вашего приложения. (Пример: в приложении iTunes Store, нажав на метку цены (0,99 долл. США и т.д.) Рядом с песней, она изменит ее на кнопку "Купить".) Это уведомление сообщает VoiceOver перечитывать текущее состояние всех доступных элементов, которые находятся на экране, и, делая это, он выясняет, что изменилось и информирует пользователя об этих изменениях. Он предупреждает VoiceOver, что макет изменился и что текущий индекс устарел, потому что элементы на экране изменили порядок.

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);