API-интерфейсы Material, Compose UI и Foundation по умолчанию реализуют и предлагают множество доступных практик. Они содержат встроенную семантику, соответствующую их конкретной роли и функциям, а это означает, что большая часть поддержки специальных возможностей обеспечивается практически без дополнительной работы.
Использование соответствующих API для соответствующих целей обычно означает, что компоненты имеют предопределенные варианты поведения специальных возможностей, которые охватывают стандартные случаи использования, но не забудьте дважды проверить, соответствуют ли эти значения по умолчанию вашим потребностям в специальных возможностях. Если нет, Compose также предоставляет способы удовлетворить более конкретные требования.
Знание семантики и шаблонов специальных возможностей по умолчанию в API Compose помогает понять, как их использовать с учетом специальных возможностей, а также поддерживать специальные возможности в большем количестве пользовательских компонентов.
Минимальные размеры сенсорных целей
Любой элемент на экране, на который кто-то может нажать, коснуться или взаимодействовать с ним, должен быть достаточно большим для надежного взаимодействия. При определении размера этих элементов обязательно установите минимальный размер 48 dp, чтобы правильно следовать рекомендациям по доступности Material Design .
Компоненты материала, такие как Checkbox
, RadioButton
, Switch
, Slider
и Surface
устанавливают этот минимальный размер внутри себя, но только тогда, когда компонент может получать действия пользователя. Например, если для параметра onCheckedChange
Checkbox
установлено значение, отличное от NULL, флажок включает в себя отступы, чтобы ширина и высота составляли не менее 48 dp.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }

Если для параметра onCheckedChange
установлено значение null, заполнение не включается, поскольку с компонентом нельзя взаимодействовать напрямую.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }

При реализации элементов управления выбором, таких как Switch
, RadioButton
или Checkbox
, вы обычно переносите интерактивное поведение в родительский контейнер, устанавливая для обратного вызова щелчка на составном элементе значение null
и добавляя toggleable
или selectable
модификатор к родительскому составному элементу.
@Composable private fun CheckableRow() { MaterialTheme { var checked by remember { mutableStateOf(false) } Row( Modifier .toggleable( value = checked, role = Role.Checkbox, onValueChange = { checked = !checked } ) .padding(16.dp) .fillMaxWidth() ) { Text("Option", Modifier.weight(1f)) Checkbox(checked = checked, onCheckedChange = null) } } }

Если размер интерактивного составного объекта меньше минимального размера сенсорного объекта, Compose все равно увеличивает размер сенсорного объекта. Это достигается за счет расширения размера цели касания за пределы компонуемого объекта.
Следующий пример содержит очень маленький кликабельный Box
. Целевая область касания автоматически расширяется за границы Box
, поэтому нажатие рядом с Box
по-прежнему вызывает событие щелчка.
@Composable private fun SmallBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .size(1.dp) ) } }

Чтобы предотвратить возможное перекрытие сенсорных областей разных составных элементов, всегда используйте достаточно большой минимальный размер для составного объекта. В данном примере это будет означать использование модификатора sizeIn
для установки минимального размера внутреннего блока:
@Composable private fun LargeBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .sizeIn(minWidth = 48.dp, minHeight = 48.dp) ) } }

Графические элементы
Когда вы определяете компонуемое Image
или Icon
, платформа Android не может автоматически понять, что отображает приложение. Вам необходимо передать текстовое описание графического элемента.
Представьте себе экран, на котором пользователь может поделиться текущей страницей с друзьями. Этот экран содержит кликабельный значок «Поделиться»:

Основываясь только на значке, платформа Android не может описать его пользователю с ослабленным зрением. Платформе Android требуется дополнительное текстовое описание значка.
Параметр contentDescription
описывает графический элемент. Используйте локализованную строку, поскольку она видна пользователю.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Некоторые графические элементы носят чисто декоративный характер, и вы, возможно, не захотите сообщать о них пользователю. Когда вы устанавливаете для параметра contentDescription
значение null
, вы указываете платформе Android, что этот элемент не имеет связанных действий или состояния.
@Composable private fun PostImage(post: Post, modifier: Modifier = Modifier) { val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1) Image( painter = image, // Specify that this image has no semantic meaning contentDescription = null, modifier = modifier .size(40.dp, 40.dp) .clip(MaterialTheme.shapes.small) ) }
contentDescription
в основном предназначен для использования с графическими элементами, такими как изображения. Компоненты материалов, такие как Button
или Text
, и интерактивные варианты поведения, такие как clickable
или toggleable
, имеют другую предопределенную семантику, описывающую их внутреннее поведение, и могут быть изменены с помощью других API Compose.
Интерактивные элементы
API-интерфейсы Material и Foundation Compose создают элементы пользовательского интерфейса, с которыми пользователи могут взаимодействовать с помощью clickable
и toggleable
API-модификаторов. Поскольку интерактивные компоненты могут состоять из нескольких элементов, clickable
и toggleable
по умолчанию объединяют семантику своих дочерних элементов, так что компонент рассматривается как один логический объект.
Например, Button
материала может состоять из дочернего значка и текста. Вместо того, чтобы рассматривать дочерние элементы как отдельные элементы, кнопка материала по умолчанию объединяет семантику своих дочерних элементов, чтобы службы доступности могли группировать их соответствующим образом:

Аналогичным образом, использование модификатора clickable
также приводит к тому, что компонуемый объект объединяет семантику своих потомков в единый объект, который отправляется в службы доступности с соответствующим представлением действия:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
Вы также можете установить конкретный onClickLabel
для родительского элемента, который можно кликнуть, чтобы предоставить дополнительную информацию службам доступности и предложить более четкое представление действия:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
Если использовать TalkBack в качестве примера, этот clickable
модификатор и его метка щелчка позволят TalkBack предоставлять подсказку к действию «Двойное нажатие, чтобы открыть эту статью», а не более общий ответ по умолчанию «Двойное нажатие, чтобы активировать».
Эта обратная связь меняется в зависимости от типа действия. При длительном нажатии на TalkBack появится подсказка «Двойное нажатие и удержание», за которой последует метка:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
В некоторых случаях у вас может не быть прямого доступа к clickable
модификатору (например, если он установлен где-то на нижнем вложенном слое), но вы все равно захотите изменить метку объявления по умолчанию. Для этого разделите настройку clickable
от изменения объявления с помощью модификатора semantics
и установки там метки клика, чтобы изменить представление действия:
@Composable private fun ArticleList(openArticle: () -> Unit) { NestedArticleListItem( // Clickable is set separately, in a nested layer: onClickAction = openArticle, // Semantics are set here: modifier = Modifier.semantics { onClick( label = "Open this article", action = { // Not needed here: openArticle() true } ) } ) }
В этом случае вам не нужно передавать действие щелчка дважды, поскольку существующие API Compose, такие как clickable
или Button
, сделают это за вас. Это связано с тем, что логика слияния гарантирует, что самая внешняя метка модификатора и действие будут предприняты для имеющейся информации.
В предыдущем примере действие щелчка openArticle()
передается глубоко вниз NestedArticleListItem
автоматически в его clickable
семантику и может быть оставлено нулевым во втором действии модификатора семантики. Однако метка клика взята из второго модификатора семантики onClick(label = "Open this article")
, поскольку она не присутствовала в первом.
Вы можете столкнуться со сценариями, в которых вы ожидаете, что дочерняя семантика будет объединена с родительской, но этого не происходит. См. раздел «Слияние и очистка» для получения более подробной информации.
Пользовательские компоненты
Для пользовательских компонентов, как правило, посмотрите на реализацию аналогичного компонента в библиотеке материалов или других библиотеках Compose и имитируйте или измените его поведение доступности, где это разумно.
Например, если вы заменяете Checkbox
«Материал» своей собственной реализацией, просмотр существующей реализации флажка напомнит вам о необходимости добавить модификатор triStateToggleable
, который обрабатывает свойства доступности для этого компонента.
Кроме того, активно используйте модификаторы Foundation, поскольку они включают в себя соображения доступности по умолчанию, а также существующие методы Compose, описанные в этом разделе.
Вы также можете найти пример пользовательского компонента-переключателя в разделе «Очистить и установить семантику» , а более подробную информацию о том, как поддерживать специальные возможности в пользовательских компонентах, можно найти в рекомендациях по API .
{% дословно %}Рекомендуется для вас
- Примечание. Текст ссылки отображается, когда JavaScript отключен.
- Доступность в Compose
- [Material Design 2 в Compose][19]
- Тестирование макета Compose