Для оказания помощи пользователям с особыми потребностями платформа Android позволяет создавать службы доступности, которые могут отображать контент из приложений для пользователей, а также управлять приложениями от их имени.
Android предоставляет ряд системных служб специальных возможностей, в том числе следующие:
- TalkBack : помогает людям с ослабленным зрением или слепотой. Он озвучивает контент с помощью синтезированного голоса и выполняет действия в приложении в ответ на жесты пользователя.
- Функция Switch Access помогает людям с двигательными нарушениями. Она выделяет интерактивные элементы и выполняет действия в ответ на нажатие пользователем кнопки. Позволяет управлять устройством с помощью всего одной или двух кнопок.
Чтобы помочь людям с ограниченными возможностями успешно использовать ваше приложение, оно должно соответствовать передовым методам, описанным на этой странице, которые основаны на рекомендациях, изложенных в разделе «Сделайте приложения более доступными» .
Каждая из этих передовых практик, описанных в следующих разделах, может дополнительно улучшить доступность вашего приложения:
- Элементы меток
- Пользователи должны понимать содержание и назначение каждого интерактивного и значимого элемента пользовательского интерфейса в вашем приложении.
- Добавить действия для обеспечения доступности
- Добавив действия, обеспечивающие доступность, вы можете позволить пользователям специальных сервисов выполнять важные пользовательские действия в вашем приложении.
- Используйте встроенные функции доступности.
- Compose по умолчанию предлагает множество вариантов обеспечения доступности. Воспользуйтесь предопределенными вариантами, чтобы сделать ваши компоненты доступными с минимальными дополнительными усилиями или без них. Compose также предоставляет способы поддержки более специфических требований к доступности, не охватываемых функциями по умолчанию.
- Используйте не только цветовые подсказки.
- Пользователи должны иметь возможность четко различать категории элементов в пользовательском интерфейсе. Для этого используются узоры и позиционирование, а также цвет, чтобы выразить эти различия.
- Сделайте медиаконтент более доступным.
- Добавьте описания к видео- или аудиоконтенту вашего приложения, чтобы пользователям, просматривающим этот контент, не приходилось полагаться исключительно на визуальные или звуковые подсказки.
Элементы меток
Важно предоставить пользователям полезные и информативные метки для каждого интерактивного элемента пользовательского интерфейса в вашем приложении. Каждая метка должна объяснять семантику конкретного элемента — то есть его значение и назначение. Программы чтения с экрана, такие как TalkBack, могут озвучивать эти метки пользователям.
В большинстве случаев API Compose и Material по умолчанию поддерживают специальные возможности . Однако, если вам необходимо вручную указать семантические свойства элемента пользовательского интерфейса, используйте модификатор semantics и свойство contentDescription . Дополнительную информацию о семантике см. в разделе «Семантика» .
В следующих разделах описаны несколько других методов маркировки.
Редактируемые элементы
При обозначении редактируемых элементов, таких как текстовые поля, полезно отображать текст с примером допустимого ввода непосредственно в элементе, а также предоставлять этот пример текста программам чтения с экрана. В таких ситуациях можно использовать текст-заполнитель, также называемый текстом-подсказкой.
В следующем примере TextField имеет параметр- placeholder , который предоставляет текст подсказки.
val usernameState = rememberTextFieldState() TextField( state = usernameState, lineLimits = TextFieldLineLimits.SingleLine, placeholder = { Text("Enter Username") } )
Также часто текстовое поле имеет соответствующую описательную метку, которая указывает, что именно пользователь должен ввести.
В следующем примере TextField имеет параметр label , который предоставляет описание доступности.
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
Для получения дополнительной информации о текстовом и пользовательском вводе см. раздел «Настройка текстовых полей» .
Элементы в коллекции
При добавлении меток к элементам коллекции каждая метка должна быть уникальной. Таким образом, службы доступности системы смогут ссылаться ровно на один элемент на экране при объявлении метки. Это соответствие позволяет пользователям понимать, когда они перемещаются по пользовательскому интерфейсу или когда фокус перемещается на элемент, который они уже обнаружили.
Например, если у вас есть LazyColumn или LazyRow , используйте модификатор semantics , чтобы присвоить каждому элементу уникальный collectionItemInfo , как показано в следующем фрагменте кода:
MilkyWayList( modifier = Modifier .semantics { collectionInfo = CollectionInfo( rowCount = milkyWay.count(), columnCount = 1 ) } ) { milkyWay.forEachIndexed { index, text -> Text( text = text, modifier = Modifier.semantics { collectionItemInfo = CollectionItemInfo(index, 0, 0, 0) } ) } }
Для получения дополнительной информации о семантических свойствах списков и таблиц см. раздел «Информация о списках и элементах» .
Группы связанного контента
Если ваше приложение отображает несколько элементов пользовательского интерфейса, образующих естественную группу, например, сведения о песне или атрибуты сообщения, расположите эти элементы внутри родительского контейнера (например, Column , Row или Box ). Используйте модификатор semantics родительского контейнера, чтобы установить mergeDescendants в true .
Таким образом, службы обеспечения доступности могут последовательно отображать описания содержимого внутренних элементов в одном сообщении. Объединение связанных элементов помогает пользователям вспомогательных технологий более эффективно находить информацию на экране.
В следующем фрагменте кода компонент Row выступает в качестве родительского контейнера. Внутри Row находятся связанные элементы, отображающие метаданные для записи в блоге — аватар автора, имя автора и предполагаемое время чтения. Установка параметра mergeDescendants в true группирует эти внутренние элементы, чтобы службы доступности могли рассматривать их как единое целое.
@Composable private fun PostMetadata(metadata: Metadata) { // Merge elements below for accessibility purposes Row(modifier = Modifier.semantics(mergeDescendants = true) {}) { Image( imageVector = Icons.Filled.AccountCircle, contentDescription = null // decorative ) Column { Text(metadata.author.name) Text("${metadata.date} • ${metadata.readTimeMinutes} min read") } } }
При группировке связанных элементов, как в предыдущем примере, сделайте интерактивным только родительский контейнер. Избегайте добавления clickable или focusable модификаторов к внутренним дочерним элементам. Вместо этого примените модификаторы к родительской Row или Column .
Поскольку службы обеспечения доступности озвучивают описания внутренних элементов одним сообщением, важно, чтобы каждое описание было как можно короче, но при этом передавало смысл элемента.
Примечание: Как правило, при создании описания содержимого для группы следует избегать объединения текста ее дочерних элементов. Это делает описание группы ненадежным, и при изменении текста дочернего элемента описание группы может перестать соответствовать видимому тексту.
В контексте списка или сетки программа чтения с экрана может объединить текст дочерних текстовых узлов элемента списка или сетки. Лучше избегать изменения этого объявления.
Для получения дополнительной информации о семантике слияния см. раздел «Слияние и очистка» .
Заголовки в тексте
В некоторых приложениях заголовки используются для обобщения групп текста, отображаемых на экране. Если определенный элемент представляет собой заголовок, вы можете указать его назначение для служб доступности, задав свойство heading в модификаторе semantics .
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
Пользователи сервисов для людей с ограниченными возможностями могут выбирать между заголовками, а не между абзацами или словами. Такая гибкость улучшает удобство навигации по тексту.
Для получения дополнительной информации о свойстве семантики heading см. раздел «Заголовки» .
Заголовки панелей доступности
В Android 9 (уровень API 28) и выше можно задавать заголовки, адаптированные для людей с ограниченными возможностями, для панелей экрана. В целях обеспечения доступности панель — это визуально выделяющаяся часть окна.
Чтобы службы специальных возможностей могли понимать поведение панели, подобное поведению окна, присвойте панелям вашего приложения описательные заголовки. Тогда службы специальных возможностей смогут предоставлять пользователям более подробную информацию об изменении внешнего вида или содержимого панели.
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
Для получения дополнительной информации о свойстве семантики paneTitle см. раздел «Окноподобные компоненты» .
Декоративные элементы
Если элемент в вашем пользовательском интерфейсе существует только для визуального отступа или улучшения внешнего вида, установите для этого элемента соответствующие свойства, указывающие на то, что службы доступности могут его игнорировать.
Для составных элементов типа Image или Icon установите contentDescription = null . Для других чисто декоративных элементов, не предоставляющих контекста или функциональности, можно использовать hideFromAccessibility . Это семантическое свойство указывает службам доступности игнорировать элемент.
Если интерактивный компонент содержит декоративные неинтерактивные дочерние элементы, используйте clearAndSetSemantics , чтобы гарантировать, что службы доступности не будут их обрабатывать. Обратите внимание, что clearAndSetSemantics полностью удаляет семантику элемента и его дочерних элементов по умолчанию. Это позволяет определить новый, унифицированный элемент доступности. Обычно этот подход используется для сложных пользовательских компонентов.
В следующем примере Icon и Text являются декоративными дочерними элементами внутри пользовательского переключателя. Чтобы предотвратить обход этих дочерних элементов службами доступности по отдельности, вы можете очистить их семантику, используя clearAndSetSemantics для родительской Row . Это указывает службам доступности рассматривать всю Row как проходимый переключатель:
// Developer might intend this to be a toggleable. // Using `clearAndSetSemantics`, on the Row, a clickable modifier is applied, // a custom description is set, and a Role is applied. @Composable fun FavoriteToggle() { val checked = remember { mutableStateOf(true) } Row( modifier = Modifier .toggleable( value = checked.value, onValueChange = { checked.value = it } ) .clearAndSetSemantics { stateDescription = if (checked.value) "Favorited" else "Not favorited" toggleableState = ToggleableState(checked.value) role = Role.Switch }, ) { Icon( imageVector = Icons.Default.Favorite, contentDescription = null // not needed here ) Text("Favorite?") } }
Для получения дополнительной информации о семантике очистки см. раздел «Очистка и установка семантики» .
Добавить действия для обеспечения доступности
Важно убедиться, что пользователи сервисов обеспечения доступности имеют возможность пройти все пользовательские сценарии в вашем приложении.
Если взаимодействие вашего пользовательского компонента изменяет состояние приложения неочевидным образом, предоставьте описательные метки для стандартных действий касания, используя параметры, такие как onClickLabel или onLongClickLabel в Modifier.clickable или Modifier.combinedClickable .
Для сложных взаимодействий, которые нельзя сопоставить со стандартными нажатиями, используйте customActions .
Например, если ваше приложение позволяет пользователям перетаскивать элемент в другое место или проводить пальцем по элементу в списке, вы можете предоставить альтернативный способ выполнения этих действий, сделав их доступными для служб специальных возможностей. Таким образом, пользователи TalkBack, Voice Access или Switch Access смогут выполнять действия, которые в противном случае были бы доступны только с помощью жестов.
В Compose можно определить пользовательские действия для обеспечения доступности с помощью свойства customActions в модификаторе semantics , используя CustomAccessibilityAction .
Например, если ваше приложение позволяет пользователям закрывать элементы, проводя пальцем по ним, вы можете предоставить доступ к этой функциональности через настраиваемое действие специальных возможностей:
SwipeToDismissBox( modifier = Modifier.semantics { // Represents the swipe to dismiss for accessibility customActions = listOf( CustomAccessibilityAction( label = "Remove article from list", action = { removeArticle() true } ) ) }, state = rememberSwipeToDismissBoxState(), backgroundContent = {} ) { ArticleListItem() }
Благодаря реализованной функции настройки специальных возможностей, пользователи могут получить к ней доступ через меню действий.
Для получения дополнительной информации о пользовательских действиях см. раздел «Пользовательские действия» .
Сделайте доступные действия понятными.
Когда элемент пользовательского интерфейса поддерживает такие действия, как касание и удержание, служба специальных возможностей, например TalkBack, объявляет об этом как «Двойное касание с удержанием для длительного нажатия».
Это общее сообщение не даёт пользователю никакой информации о том, что делает действие «касание и удержание».
Чтобы сделать это объявление более полезным, укажите содержательное описание действия.
В Compose стандартные модификаторы взаимодействия, такие как clickable и combinedClickable имеют встроенные параметры (а именно onClickLabel и onLongClickLabel ), которые можно использовать для описания действий, как показано в следующем примере:
var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) } val haptics = LocalHapticFeedback.current LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) { items(photos, { it.id }) { photo -> ImageItem( photo, Modifier .combinedClickable( onClick = { activePhotoId = photo.id }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) contextMenuPhotoId = photo.id }, onLongClickLabel = stringResource(R.string.open_context_menu) ) ) } } if (contextMenuPhotoId != null) { PhotoActionsSheet( photo = photos.first { it.id == contextMenuPhotoId }, onDismissSheet = { contextMenuPhotoId = null } ) }
В результате TalkBack объявляет «Открыть контекстное меню», помогая пользователям понять цель действия.
Вы также можете указать метку непосредственно в модификаторе semantics .
Для получения дополнительной информации о реагировании на касания и щелчки см. разделы «Касание и нажатие» и «Интерактивные элементы» .
Используйте встроенные функции доступности.
При разработке пользовательского интерфейса вашего приложения воспользуйтесь встроенными функциями доступности, чтобы избежать повторной реализации уже существующей функциональности. API Material, Compose UI и Foundation по умолчанию реализуют и предлагают множество методов обеспечения доступности.
В Jetpack Compose используйте встроенные компоненты, такие как Button , Switch и Checkbox для создания доступных пользовательских интерфейсов. Эти компоненты поставляются с предустановленными модификаторами semantics , такими как role и stateDescription , которые можно использовать для повышения доступности ваших приложений.
Примените семантику к пользовательским компонентам.
При создании пользовательского компонента следует учитывать, какая поддержка доступности необходима этому компоненту для выполнения своей функции. Часто стандартных API Compose, которые вы уже используете — таких как clickable , toggleable или selectable — достаточно, поскольку они автоматически заполняют дерево семантики.
Однако для некоторых компонентов требуется более специфичная информация, чем та, которую предоставляют стандартные модификаторы. В таких случаях следует искать специализированные модификаторы (например, triStateToggleable ) или, если таковых нет, явно указать семантику, используя низкоуровневый Modifier.semantics .
Например, рассмотрим TriStateSwitch переключатель (TriStateSwitch), имеющий три состояния (включено, выключено и неопределенное).
В то время как стандартный модификатор toggleable предполагает два состояния, модификатор triStateToggleable обрабатывает сложность третьего состояния. Он автоматически устанавливает Role доступности ( Switch ) и State . Таким образом, службы доступности получают точную информацию, и вам не нужно вручную определять семантику.
Следующий фрагмент кода демонстрирует работу TriStateSwitch с использованием этого подхода:
@Composable fun TriStateSwitch( state: ToggleableState, onClick: () -> Unit, modifier: Modifier = Modifier ) { // A real implementation would include custom drawing for the switch. // This example uses a Box to demonstrate the semantics. Box( modifier = modifier .size(width = 64.dp, height = 40.dp) // triStateToggleable handles the semantics (Role and State) // automatically, so explicit Modifier.semantics is not needed here. .triStateToggleable( state = state, onClick = onClick, role = Role.Switch ) // Add visual feedback based on the state .background( when (state) { ToggleableState.On -> Color.Green ToggleableState.Off -> Color.Gray ToggleableState.Indeterminate -> Color.Yellow } ) ) } // Usage within another composable: var state by remember { mutableStateOf(ToggleableState.Off) } TriStateSwitch( state = state, onClick = { state = when (state) { ToggleableState.Off -> ToggleableState.Indeterminate ToggleableState.Indeterminate -> ToggleableState.On ToggleableState.On -> ToggleableState.Off } } )
При создании пользовательского компонента убедитесь, что вы указали все необходимые семантические свойства для обеспечения доступности. Например, если ваш компонент имитирует стандартный элемент управления, такой как переключатель или кнопка, эти свойства включают роль компонента (например, Role.Switch или Role.Button ), stateDescription (например, "Вкл.", "Выкл.", "Выбрано" или "Не выбрано") и любые соответствующие метки действий. Для получения дополнительной информации см. раздел «Пользовательские компоненты ».
Используйте не только цветовые подсказки.
Чтобы помочь пользователям с нарушениями цветового зрения, используйте другие подсказки, помимо цвета, для различения элементов пользовательского интерфейса на экранах вашего приложения. Эти методы могут включать использование различных форм или размеров, текстовых или визуальных узоров, а также добавление звуковой или тактильной обратной связи для обозначения различий между элементами.
На рисунке 1 показаны два варианта выполнения действия. В одном варианте для различения двух возможных действий в рабочем процессе используется только цвет. В другом варианте, в дополнение к цвету, используется передовая практика включения фигур и текста для выделения различий между двумя вариантами:
Сделайте медиаконтент более доступным.
Если вы разрабатываете приложение, содержащее медиаконтент, например, видеоролик или аудиозапись, постарайтесь обеспечить пользователям с различными потребностями в доступности возможность понимания материала. В частности, попробуйте сделать следующее:
- Включите элементы управления, позволяющие пользователям приостанавливать или останавливать воспроизведение медиафайлов, регулировать громкость и включать/выключать субтитры.
- Если видео содержит информацию, необходимую для выполнения рабочего процесса, предоставьте тот же контент в альтернативном формате, например, в виде стенограммы.
Дополнительные ресурсы
Для получения дополнительной информации о том, как сделать ваше приложение более доступным, ознакомьтесь со следующими дополнительными ресурсами: