Las APIs de Material, Compose UI y Foundation implementan y ofrecen muchas prácticas de accesibilidad de forma predeterminada. Contienen semánticas integradas que siguen su rol y función específicos, lo que significa que la mayor parte de la compatibilidad con la accesibilidad se proporciona con poco o ningún trabajo adicional.
El uso de las APIs adecuadas para el propósito adecuado suele significar que los componentes incluyen comportamientos de accesibilidad predefinidos que abarcan casos de uso estándar, pero recuerda verificar si estos valores predeterminados se ajustan a tus necesidades de accesibilidad. De lo contrario, Compose también proporciona formas de abordar requisitos más específicos.
Conocer la semántica y los patrones de accesibilidad predeterminados en las APIs de Compose ayuda a comprender cómo usarlos teniendo en cuenta la accesibilidad, así como a admitir la accesibilidad en componentes más personalizados.
Tamaños mínimos del objetivo táctil
Todos los elementos de la pantalla en los que se puede hacer clic, que se pueden tocar o con los que se puede interactuar deben ser lo suficientemente grandes para permitir una interacción confiable. Cuando establezcas el tamaño de esos elementos, asegúrate de configurar su tamaño mínimo en 48 dp para seguir los Lineamientos de Accesibilidad de Material Design.
Los componentes de Material, como Checkbox
, RadioButton
, Switch
, Slider
y Surface
, establecen este tamaño mínimo de manera interna, pero solo cuando el componente puede recibir acciones del usuario. Por ejemplo, si Checkbox
tiene su parámetro onCheckedChange
establecido en un valor no nulo, la casilla de verificación incluye un padding para tener un ancho y una altura de 48 dp como mínimo.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }

Cuando el parámetro onCheckedChange
se establece en nulo, el padding no se incluye, ya que no se puede interactuar directamente con el componente.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }

Cuando implementas controles de selección como Switch
, RadioButton
o Checkbox
, por lo general, quitas el comportamiento de hacer clic en un contenedor superior, configuras la devolución de llamada de clics en el elemento componible a null
y agregas un modificador toggleable
o selectable
al elemento superior que admite composición.
@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) } } }

Cuando el tamaño de un elemento componible para hacer clic es menor que el tamaño del objetivo táctil mínimo, Compose aumenta el tamaño del objetivo táctil. Para ello, expande el tamaño del objetivo fuera de los límites del elemento componible.
El siguiente ejemplo contiene un objeto Box
muy pequeño para hacer clic. El área del objetivo táctil se expande automáticamente más allá de los límites de Box
, por lo que, cuando se presione junto a Box
, se activará el evento de clic.
@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) ) } }

Para evitar una posible superposición entre áreas táctiles de diferentes elementos componibles, siempre usa un tamaño mínimo lo suficientemente grande para el elemento componible. En el ejemplo, eso implicaría usar el modificador sizeIn
para establecer el tamaño mínimo del cuadro interno:
@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) ) } }

Elementos gráficos
Cuando defines un elemento componible Image
o Icon
, no existe una manera automática de que el framework de Android comprenda lo que muestra la app. Debes pasar una descripción textual del elemento gráfico.
Imagina una pantalla en la que el usuario pueda compartir la página actual con amigos. Esta pantalla contiene un ícono para compartir en el que se puede hacer clic:

Solamente en función del ícono, el framework de Android no puede describirlo a un usuario con discapacidad visual. El framework de Android necesita una descripción textual adicional del ícono.
El parámetro contentDescription
describe un elemento gráfico. Usa una cadena localizada, ya que el usuario la puede ver.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Algunos elementos gráficos son puramente decorativos, y es posible que no quieras comunicárselos al usuario. Cuando configuras el parámetro contentDescription
como null
, le indicas al framework de Android que ese elemento no tiene acciones ni estado asociados.
@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
se diseñó principalmente para usarse en elementos gráficos, como imágenes. Los componentes de Material, como Button
o Text
, y los comportamientos prácticos, como clickable
o toggleable
, incluyen otras semánticas predefinidas que describen su comportamiento intrínseco y se pueden cambiar a través de otras APIs de Compose.
Elementos interactivos
Las APIs de Material y Foundation Compose crean elementos de la IU con los que los usuarios pueden interactuar a través de las APIs de modificadores clickable
y toggleable
. Debido a que los componentes interactivos pueden constar de varios elementos, clickable
y toggleable
combinan las semánticas de sus elementos secundarios de forma predeterminada, de modo que el componente se trate como una entidad lógica.
Por ejemplo, un Button
de Material puede constar de un ícono secundario y un poco de texto.
En lugar de tratar a los elementos secundarios como elementos individuales, un botón de Material combina su semántica secundaria de forma predeterminada, de modo que los servicios de accesibilidad puedan agruparlos de la siguiente manera:

De manera similar, usar el modificador clickable
también hace que un elemento componible combine la semántica de sus descendientes en una sola entidad, que se envía a los servicios de accesibilidad con una representación de acción correspondiente:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
También puedes establecer un onClickLabel
específico en el elemento superior en el que se pueda hacer clic para proporcionar información adicional a los servicios de accesibilidad y ofrecer una representación más refinada de la acción:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
Tomando como ejemplo TalkBack, este modificador clickable
y su etiqueta de clic permitirían que TalkBack proporcione una sugerencia de acción de "Presiona dos veces para abrir este artículo", en lugar del mensaje predeterminado más genérico de "Presiona dos veces para activar".
Estos comentarios cambian según el tipo de acción. Un clic largo proporcionaría una sugerencia de TalkBack de "Mantén presionado para", seguida de una etiqueta:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
En algunos casos, es posible que no tengas acceso directo al modificador clickable
(por ejemplo, cuando se establece en algún lugar de una capa anidada inferior),pero aún así quieras cambiar la etiqueta de anuncio de la predeterminada. Para ello, divide la configuración de clickable
de la modificación del anuncio con el modificador semantics
y establece la etiqueta de clic allí para modificar la representación de la acción:
@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 } ) } ) }
En este caso, no necesitas pasar la acción de clic dos veces, ya que las APIs existentes de Compose, como clickable
o Button
, lo controlan por ti. Esto se debe a que la lógica de combinación garantiza que se tomen la etiqueta y la acción de modificador más externos para la información que está presente.
En el ejemplo anterior, NestedArticleListItem
pasa automáticamente la acción de clic openArticle()
a su semántica clickable
y se puede dejar nula en la segunda acción de modificador de semántica. Sin embargo, la etiqueta de clic se toma del segundo modificador de semántica onClick(label = "Open this article")
, ya que no estaba presente en el primero.
Es posible que te encuentres con situaciones en las que esperas que la semántica de los elementos secundarios se combine en una superior, pero eso no sucede. Consulta Cómo combinar y borrar para obtener información más detallada.
Componentes personalizados
En el caso de los componentes personalizados, como regla general, observa la implementación de un componente similar en la biblioteca de Material o en otras bibliotecas de Compose, y fíjate en su comportamiento de accesibilidad para imitarlo o modificarlo cuando sea conveniente.
Por ejemplo, si reemplazas el objeto Checkbox
de Material con tu propia implementación, observar la implementación existente de la casilla de verificación te recordará que debes agregar el modificador triStateToggleable
, que controla las propiedades de accesibilidad de este componente.
Además, usa activamente los modificadores de Foundation, ya que incluyen consideraciones de accesibilidad de forma inmediata, así como las prácticas existentes de Compose que se abordan en esta sección.
También puedes encontrar un ejemplo de un componente de botón de activación personalizado en la sección de semántica clara y establecida, así como información más detallada sobre cómo admitir accesibilidad en componentes personalizados en los lineamientos de la API.
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Accesibilidad en Compose
- [Material Design 2 en Compose][19]
- Cómo probar tu diseño de Compose