Перейти к содержанию

Доступность

И Android, и iOS предоставляют API для интеграции приложений со вспомогательными технологиями, такими как встроенные программы чтения с экрана VoiceOver (iOS) и TalkBack (Android). React Native имеет дополнительные API, которые позволят вашему приложению адаптироваться ко всем пользователям.

Android и iOS немного отличаются в своих подходах, и поэтому реализации React Native могут отличаться в зависимости от платформы.

Свойства доступности

accessible

Когда true, указывает, что представление является элементом доступности. Когда представление является элементом доступности, оно группирует свои дочерние элементы в один выбираемый компонент. По умолчанию все сенсорные элементы являются доступными.

На Android свойство accessible={true} для react-native View будет переведено в нативное focusable={true}.

1
2
3
4
<View accessible={true}>
    <Text>text one</Text>
    <Text>text two</Text>
</View>

В приведенном выше примере мы не можем получить фокус доступности отдельно для 'text one' и 'text two'. Вместо этого мы получаем фокус на родительском представлении со свойством 'accessible'.

accessibilityLabel

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

Для использования установите свойство accessibilityLabel в пользовательскую строку на вашем View, Text или Touchable:

1
2
3
4
5
6
7
8
9
<TouchableOpacity
    accessible={true}
    accessibilityLabel="Tap me!"
    onPress={onPress}
>
    <View style={styles.button}>
        <Text style={styles.buttonText}>Press me!</Text>
    </View>
</TouchableOpacity>

В приведенном выше примере метка accessibilityLabel элемента TouchableOpacity по умолчанию будет иметь значение "Press me!". Метка строится путем объединения всех дочерних элементов узла Text, разделенных пробелами.

accessibilityLabelledBy

Ссылка на другой элемент nativeID, используемый для построения сложных форм.

Значение accessibilityLabelledBy должно соответствовать nativeID связанного элемента:

1
2
3
4
5
6
7
<View>
    <Text nativeID="formLabel">Label for Input Field</Text>
    <TextInput
        accessibilityLabel="input"
        accessibilityLabelledBy="formLabel"
    />
</View>

В приведенном выше примере экранная читалка объявляет Input, Edit Box for Label for Input Field, когда фокусируется на TextInput.

accessibilityHint

Подсказка доступности помогает пользователям понять, что произойдет, когда они выполнят действие над элементом доступности, если результат не ясен из метки доступности.

Для использования установите свойство accessibilityHint в пользовательскую строку на вашем View, Text или Touchable:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<TouchableOpacity
    accessible={true}
    accessibilityLabel="Go back"
    accessibilityHint="Navigates to the previous screen"
    onPress={onPress}
>
    <View style={styles.button}>
        <Text style={styles.buttonText}>Back</Text>
    </View>
</TouchableOpacity>

iOS

В приведенном выше примере VoiceOver будет читать подсказку после метки, если у пользователя включены подсказки в настройках VoiceOver устройства. Подробнее о рекомендациях для accessibilityHint читайте в iOS Developer Docs.

Android

В приведенном выше примере TalkBack прочитает подсказку после ярлыка. В настоящее время подсказки нельзя отключить на Android.

accessibilityLanguage

Используя свойство accessibilityLanguage, программа чтения с экрана будет понимать, какой язык использовать при чтении label, value и hint элемента. Предоставляемое строковое значение должно соответствовать спецификации BCP 47.

1
2
3
4
5
6
7
<View
    accessible={true}
    accessibilityLabel="Pizza"
    accessibilityLanguage="it-IT"
>
    <Text>🍕</Text>
</View>

accessibilityIgnoresInvertColors

Инвертирование цветов экрана — это функция доступности, которая облегчает восприятие iPhone и iPad для некоторых людей с повышенной чувствительностью к яркости, облегчает различение для некоторых людей с дальтонизмом и облегчает восприятие для некоторых людей со слабым зрением. Однако иногда у вас есть виды, например, фотографии, которые вы не хотите, чтобы были перевернуты. В этом случае вы можете установить это свойство в значение true, чтобы цвета этих видов не были инвертированы.

accessibilityLiveRegion

Когда компоненты динамически изменяются, мы хотим, чтобы TalkBack предупреждал конечного пользователя. Это возможно благодаря свойству accessibilityLiveRegion. Оно может быть установлено в none, polite и assertive:

  • none Службы доступности не должны объявлять об изменениях в этом представлении.
  • polite Службы обеспечения доступности должны объявлять об изменениях в этом представлении.
  • assertive Службы обеспечения доступности должны прерывать текущую речь, чтобы немедленно объявить об изменениях в этом представлении.
1
2
3
4
5
6
7
8
<TouchableWithoutFeedback onPress={addOne}>
  <View style={styles.embedded}>
    <Text>Click me</Text>
  </View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
  Clicked {count} times
</Text>

В приведенном выше примере метод addOne изменяет переменную состояния count. Как только конечный пользователь нажимает на TouchableWithoutFeedback, TalkBack считывает текст в представлении Text благодаря свойству accessibilityLiveRegion="polite".

accessibilityRole

accessibilityRole передает назначение компонента пользователю вспомогательной технологии.

accessibilityRole может быть одним из следующих:

  • adjustable Используется, когда элемент можно "регулировать" (например, ползунок).
  • alert Используется, когда элемент содержит важный текст, который должен быть представлен пользователю.
  • button Используется, когда элемент должен рассматриваться как кнопка.
  • checkbox Используется, когда элемент представляет флажок, который может быть установлен, снят или иметь смешанное состояние.
  • combobox Используется, когда элемент представляет собой комбинированное окно, которое позволяет пользователю выбрать один из нескольких вариантов.
  • header Используется, когда элемент выступает в качестве заголовка для раздела содержимого (например, заголовок навигационной панели).
  • image Используется, когда элемент должен рассматриваться как изображение. Может сочетаться с кнопкой или ссылкой, например.
  • imagebutton Используется, когда элемент должен рассматриваться как кнопка и одновременно является изображением.
  • keyboardkey Используется, когда элемент действует как клавиша клавиатуры.
  • link Используется, когда элемент должен рассматриваться как ссылка.
  • menu Используется, когда компонент представляет собой меню выбора.
  • menubar Используется, когда компонент является контейнером нескольких меню.
  • menuitem Используется для представления пункта в меню.
  • none Используется, когда элемент не имеет роли.
  • progressbar Используется для представления компонента, который показывает прогресс выполнения задачи.
  • radio Используется для представления радиокнопки.
  • radiogroup Используется для представления группы радиокнопок.
  • scrollbar Используется для представления полосы прокрутки.
  • search Используется, когда элемент текстового поля должен также рассматриваться как поле поиска.
  • spinbutton Используется для представления кнопки, открывающей список вариантов.
  • summary Используется, когда элемент может быть использован для предоставления краткой информации о текущих условиях в приложении при его первом запуске.
  • switch Используется для представления переключателя, который можно включать и выключать.
  • tab Используется для представления вкладки.
  • tablist Используется для представления списка вкладок.
  • text Используется, когда элемент должен рассматриваться как статичный текст, который не может изменяться.
  • timer Используется для представления таймера.
  • togglebutton Используется для представления кнопки переключения. Должна использоваться с установленным флажком accessibilityState, чтобы указать, включена или выключена кнопка.
  • toolbar Используется для представления панели инструментов (контейнер кнопок действий или компонентов).
  • grid Используется с ScrollView, VirtualizedList, FlatList или SectionList для представления сетки. Добавляет объявления о входе/выходе из сетки в android GridView.

accessibilityState

Описывает текущее состояние компонента для пользователя вспомогательной технологии.

accessibilityState — это объект. Он содержит следующие поля:

Name Description Type Required
disabled Указывает, отключен ли элемент или нет. boolean No
selected Указывает, выбран ли выбираемый элемент в данный момент или нет. boolean No
checked Указывает состояние элемента с флажком. Это поле булевое или "mixed" для смешанных флажков. boolean or 'mixed' No
busy Указывает, занят ли элемент в данный момент или нет. boolean No
expanded Указывает, является ли расширяемый элемент в данный момент развернутым или свернутым. boolean No

Для использования установите accessibilityState в объект с определенным определением.

accessibilityValue

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

accessibilityValue — это объект. Он содержит следующие поля:

Name Description Type Required
min The minimum value of this component's range. integer Required if now is set.
max The maximum value of this component's range. integer Required if now is set.
now The current value of this component's range. integer No
text A textual description of this component's value. Will override min, now, and max if set. string No

accessibilityViewIsModal

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

Например, в окне, содержащем родственные представления A и B, установка accessibilityViewIsModal в true для представления B заставляет VoiceOver игнорировать элементы в представлении A. С другой стороны, если вид B содержит дочерний вид C и вы установите accessibilityViewIsModal в true для вида C, VoiceOver не будет игнорировать элементы вида A.

accessibilityElementsHidden

Булево значение, указывающее, являются ли элементы доступности, содержащиеся в этом элементе доступности, скрытыми.

Например, в окне, содержащем родственные представления A и B, установка accessibilityElementsHidden в true для представления B заставляет VoiceOver игнорировать элементы в представлении B. Это аналогично свойству Android importantForAccessibility="no-hide-descendants".

aria-valuemax

Представляет собой максимальное значение для компонентов, основанных на диапазоне, таких как ползунки и шкалы прогресса.

aria-valuemin

Представляет собой минимальное значение для компонентов, основанных на диапазоне, таких как ползунки и индикаторы выполнения.

aria-valuenow

Представляет текущее значение для компонентов, основанных на диапазоне, таких как ползунки и шкалы прогресса.

aria-valuetuetext

Представляет собой текстовое описание компонента.

aria-busy

Указывает на то, что элемент изменяется и что вспомогательные технологии могут захотеть подождать, пока изменения не будут завершены, прежде чем информировать пользователя об обновлении.

Type Default
boolean false

aria-checked

Указывает на состояние элемента с флажком. Это поле может принимать либо булево значение, либо строку "mixed" для представления смешанных флажков.

Type Default
boolean, 'mixed' false

aria-disabled

Указывает, что элемент воспринимается, но отключен, поэтому его нельзя редактировать или использовать иным образом.

Type Default
boolean false

aria-expanded

Указывает, является ли расширяемый элемент в данный момент развернутым или свернутым.

Type Default
boolean false

aria-hidden

Указывает, являются ли элементы доступности, содержащиеся в этом элементе доступности, скрытыми.

Например, в окне, содержащем родственные представления A и B, установка aria-hidden в true для представления B заставляет VoiceOver игнорировать элементы в представлении B.

Type Default
boolean false

aria-label

Определяет строковое значение, которое маркирует интерактивный элемент.

Type
string

aria-labelledby

Определяет элемент, который маркирует элемент, к которому он применяется. Значение aria-labelledby должно соответствовать nativeID связанного элемента:

1
2
3
4
5
6
7
<View>
    <Text nativeID="formLabel">Label for Input Field</Text>
    <TextInput
        aria-label="input"
        aria-labelledby="formLabel"
    />
</View>
Type
string

aria-live

Указывает, что элемент будет обновлен, и описывает типы обновлений, которые агенты пользователя, вспомогательные технологии и пользователь могут ожидать от живого региона.

  • off Службы доступности не должны объявлять об изменениях в этом представлении.
  • polite Службы обеспечения доступности должны объявлять об изменениях в этом представлении.
  • assertive Службы доступа должны прерывать текущую речь, чтобы немедленно объявить об изменениях в этом представлении.
Type Default
enum('assertive', 'off', 'polite') 'off'

aria-modal

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

Type Default
boolean false

aria-selected

Указывает, выбран ли выбираемый элемент в данный момент или нет.

Type
boolean

importantForAccessibility

В случае двух перекрывающихся компонентов пользовательского интерфейса с одним и тем же родителем фокус доступности по умолчанию может иметь непредсказуемое поведение. Свойство importantForAccessibility решает эту проблему, контролируя, будет ли представление вызывать события доступности и сообщать ли о них службам доступности. Оно может быть установлено в auto, yes, no и no-hide-descendants (последнее значение заставит службы доступности игнорировать компонент и все его дочерние элементы).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<View style={styles.container}>
    <View
        style={[
            styles.layout,
            { backgroundColor: 'green' },
        ]}
        importantForAccessibility="yes"
    >
        <Text>First layout</Text>
    </View>
    <View
        style={[
            styles.layout,
            { backgroundColor: 'yellow' },
        ]}
        importantForAccessibility="no-hide-descendants"
    >
        <Text>Second layout</Text>
    </View>
</View>

В приведенном выше примере макет yellow и его потомки совершенно невидимы для TalkBack и всех других служб доступности. Поэтому мы можем использовать перекрывающиеся представления с одним и тем же родителем, не смущая TalkBack.

onAccessibilityEscape

Назначьте это свойство пользовательской функции, которая будет вызываться, когда кто-то выполнит жест "escape", который представляет собой Z-образный жест двумя пальцами. Функция побега должна иерархически перемещать назад в пользовательском интерфейсе. Это может означать перемещение вверх или назад в иерархии навигации или отказ от модального пользовательского интерфейса. Если выбранный элемент не имеет функции onAccessibilityEscape, система попытается перейти вверх по иерархии представлений, пока не найдет представление, которое имеет такую функцию, или выдаст "bonk", указывая, что не смогла ее найти.

onAccessibilityTap

Используйте это свойство для назначения пользовательской функции, которая будет вызываться, когда кто-то активирует доступный элемент двойным нажатием на него, когда он выбран.

onMagicTap

Назначьте это свойство пользовательской функции, которая будет вызываться при выполнении жеста "волшебный тап", представляющего собой двойное нажатие двумя пальцами. Функция "волшебного касания" должна выполнять наиболее релевантное действие, которое пользователь может выполнить на компоненте. В приложении "Телефон" на iPhone "волшебное касание" отвечает на телефонный звонок или завершает текущий. Если у выбранного элемента нет функции onMagicTap, система будет перемещаться вверх по иерархии представлений, пока не найдет представление, у которого такая функция есть.

роль

роль передает назначение компонента пользователю вспомогательной технологии. Имеет приоритет над пропсом accessibilityRole.

Роль" может быть одной из следующих:

  • alert Используется, когда элемент содержит важный текст, который должен быть представлен пользователю.
  • button Используется, когда элемент должен рассматриваться как кнопка.
  • checkbox Используется, когда элемент представляет флажок, который может быть установлен, снят или иметь смешанное состояние.
  • combobox Используется, когда элемент представляет собой комбинированное окно, которое позволяет пользователю выбирать из нескольких вариантов.
  • grid Используется с ScrollView, VirtualizedList, FlatList или SectionList для представления сетки. Добавляет объявления о входе/выходе из сетки в android GridView.
  • heading Используется, когда элемент выступает в качестве заголовка для раздела содержимого (например, заголовок навигационной панели).
  • img Используется, когда элемент должен рассматриваться как изображение. Может сочетаться, например, с кнопкой или ссылкой.
  • link Используется, когда элемент должен рассматриваться как ссылка.
  • list Используется для идентификации списка элементов.
  • menu Используется, когда компонент представляет собой меню выбора.
  • menubar Используется, когда компонент является контейнером нескольких меню.
  • menuitem Используется для представления пункта в меню.
  • none Используется, когда элемент не имеет роли.
  • presentation Используется, когда элемент не играет никакой роли.
  • progressbar Используется для представления компонента, который показывает прогресс выполнения задачи.
  • radio Используется для представления радиокнопки.
  • radiogroup Используется для представления группы радиокнопок.
  • scrollbar Используется для представления полосы прокрутки.
  • searchbox Используется, когда элемент текстового поля должен также рассматриваться как поле поиска.
  • slider Используется, когда элемент можно "регулировать" (например, ползунок).
  • spinbutton Используется для представления кнопки, открывающей список вариантов выбора.
  • summary Используется, когда элемент может быть использован для предоставления краткой информации о текущих условиях в приложении при его первом запуске.
  • switch Используется для представления переключателя, который можно включать и выключать.
  • tab Используется для представления вкладки.
  • tablist Используется для представления списка вкладок.
  • timer Используется для представления таймера.
  • toolbar Используется для представления панели инструментов (контейнер кнопок или компонентов).

Действия по обеспечению доступности

Действия доступности позволяют вспомогательной технологии программно вызывать действия компонента. Чтобы поддерживать действия доступности, компонент должен делать две вещи:

  • Определите список поддерживаемых действий с помощью свойства accessibilityActions.
  • Реализуйте функцию onAccessibilityAction для обработки запросов на выполнение действий.

Свойство accessibilityActions должно содержать список объектов действий. Каждый объект действия должен содержать следующие поля:

Name Type Required
name string Yes
label string No

Действия представляют собой либо стандартные действия, такие как нажатие на кнопку или регулировка ползунка, либо пользовательские действия, специфичные для данного компонента, например, удаление сообщения электронной почты. Поле name обязательно как для стандартных, так и для пользовательских действий, а label необязательно для стандартных действий.

При добавлении поддержки стандартных действий, name должно быть одним из следующих:

  • 'magicTap' — только для iOS — Пока фокус VoiceOver находится на компоненте или внутри него, пользователь выполнил двойное нажатие двумя пальцами.
  • 'escape' — только для iOS — пока фокус VoiceOver находится на компоненте или внутри него, пользователь выполнил жест скраба двумя пальцами (влево, вправо, влево).
  • 'activate' — Активировать компонент. Обычно это действие должно выполняться так же, как если бы пользователь коснулся или щелкнул компонент, когда не использует вспомогательную технологию. Это генерируется, когда пользователь программы чтения с экрана дважды коснется компонента.
  • 'increment' — инкремент регулируемого компонента. На iOS VoiceOver генерирует это действие, когда компонент имеет роль 'adjustable' и пользователь наводит на него фокус и проводит пальцем вверх. На Android TalkBack генерирует это действие, когда пользователь помещает фокус доступности на компонент и нажимает кнопку увеличения громкости.
  • 'decrement' — Уменьшение регулируемого компонента. На iOS VoiceOver генерирует это действие, когда компонент имеет роль 'adjustable', а пользователь помещает фокус на него и проводит пальцем вниз. На Android TalkBack генерирует это действие, когда пользователь помещает фокус доступности на компонент и нажимает кнопку уменьшения громкости.
  • 'longpress' — только для Android — Это действие генерируется, когда пользователь помещает фокус доступности на компонент и дважды нажимает и удерживает один палец на экране. Как правило, это действие должно выполняться так же, как если бы пользователь удерживал один палец на компоненте, не используя вспомогательную технологию.

Поле label является необязательным для стандартных действий и часто не используется вспомогательными технологиями. Для пользовательских действий это локализованная строка, содержащая описание действия, которое должно быть представлено пользователю.

Для обработки запросов на выполнение действия компонент должен реализовать функцию onAccessibilityAction. Единственным аргументом этой функции является событие, содержащее имя действия, которое необходимо выполнить. Приведенный ниже пример из RNTester показывает, как создать компонент, который определяет и обрабатывает несколько пользовательских действий.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<View
    accessible={true}
    accessibilityActions={[
        { name: 'cut', label: 'cut' },
        { name: 'copy', label: 'copy' },
        { name: 'paste', label: 'paste' },
    ]}
    onAccessibilityAction={(event) => {
        switch (event.nativeEvent.actionName) {
            case 'cut':
                Alert.alert('Alert', 'cut action success');
                break;
            case 'copy':
                Alert.alert('Alert', 'copy action success');
                break;
            case 'paste':
                Alert.alert(
                    'Alert',
                    'paste action success'
                );
                break;
        }
    }}
/>

Проверка, включено ли устройство чтения с экрана

API AccessibilityInfo позволяет определить, активен ли в данный момент экранный считыватель. Подробности см. в документации AccessibilityInfo.

Отправка событий доступности

Иногда бывает полезно вызвать событие доступности на компоненте пользовательского интерфейса (например, когда пользовательское представление появляется на экране или устанавливается фокус доступности на представление). Нативный модуль UIManager предоставляет для этой цели метод 'sendAccessibilityEvent'. Он принимает два аргумента: тег представления и тип события. Поддерживаемые типы событий: typeWindowStateChanged, typeViewFocused и typeViewClicked.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import {
    Platform,
    UIManager,
    findNodeHandle,
} from 'react-native';

if (Platform.OS === 'android') {
    UIManager.sendAccessibilityEvent(
        findNodeHandle(this),
        UIManager.AccessibilityEventTypes.typeViewFocused
    );
}

Тестирование поддержки TalkBack

Чтобы включить TalkBack, перейдите в приложение "Настройки" на устройстве Android или эмуляторе. Нажмите пункт Доступность, затем TalkBack. Переключите переключатель "Использовать сервис", чтобы включить или отключить его.

В эмуляторах Android по умолчанию не установлен TalkBack. Вы можете установить TalkBack на свой эмулятор через магазин Google Play. Убедитесь, что вы выбрали эмулятор с установленным магазином Google Play. Они доступны в Android Studio.

Для переключения TalkBack можно использовать сочетание клавиш громкости. Чтобы включить сочетание клавиш громкости, перейдите в приложение "Настройки", затем "Доступность". В самом верху включите пункт "Ярлык клавиши громкости".

Чтобы воспользоваться сочетанием клавиш громкости, нажмите обе клавиши громкости и удерживайте их в течение 3 секунд, чтобы запустить инструмент доступности.

Кроме того, при желании вы можете переключить TalkBack через командную строку:

1
2
3
4
5
# disable
adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService

# enable
adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService

Тестирование поддержки VoiceOver

Чтобы включить VoiceOver, перейдите в приложение "Настройки" на устройстве iOS (оно недоступно для симулятора). Нажмите пункт Общие, затем Доступность. Там вы найдете множество инструментов, которые люди используют, чтобы сделать свои устройства более удобными для использования, например, более жирный текст, повышенный контраст и VoiceOver.

Чтобы включить VoiceOver, нажмите на VoiceOver в разделе "Зрение" и переключите переключатель, который появится вверху.

В самом низу настроек доступности находится "Ярлык доступности". С его помощью можно переключить VoiceOver, трижды нажав кнопку Home.

Дополнительные ресурсы

Комментарии