Search code examples
androidandroid-jetpack-composetalkback

Why compose adds extra text to Accessibility?


So I'm working on the Accessibility feature in my app.

My problem is, the TalkBack announces extra texts regardless of the clearAndSetSemantics{} fun.

For example to the close button it says: "Close button content desctiption, button Out of list" instead of "Close button content desctiption, button" or for every star it announces: "1 Rating icon item double tap to activate" instead of "1 Rating icon item".

You can reproduce the issue with this code:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun Example(modifier: Modifier = Modifier) {
    Column(
        modifier = modifier
            .fillMaxWidth()
            .semantics {
                isTraversalGroup = true
            }
            .background(Color.White)
    ) {
        IconButton(
            modifier = Modifier
                .clearAndSetSemantics {
                    contentDescription = "Close button content desctiption, button"
                    testTag = "closeButtonTextTag"
                },
            onClick = {}
        ) {
            Icon(
                Icons.Default.Close,
                contentDescription = ""
            )
        }

        Spacer(modifier = Modifier.height(16.dp))

        Text(text = "Text one description")

        Spacer(modifier = Modifier.height(16.dp))

        Text(text = "Text two description")

        Spacer(modifier = Modifier.height(16.dp))

        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.Absolute.SpaceEvenly
        ) {
            for (ratingIndex in 1..5) {
                Column(
                    modifier = Modifier.weight(1f)
                ) {
                    Icon(
                        modifier = Modifier
                            .size(30.dp)
                            .align(Alignment.CenterHorizontally)
                            .clickable {

                            }
                            .clearAndSetSemantics {
                                contentDescription = "$ratingIndex Rating icon item"
                                testTag = "ratingIconTestTag"
                            },
                        imageVector = if (ratingIndex < 3) {
                            Icons.Default.Star
                        } else {
                            Icons.Filled.Star
                        },
                        contentDescription = "",
                        tint = Color.Unspecified
                    )

                    Text(
                        modifier = Modifier
                            .padding(vertical = 8.dp)
                            .semantics {
                                invisibleToUser()
                                testTag = "textTestTag"
                            },
                        text = "Last text string"
                    )
                }
            }
        }
    }
}

@Preview
@Composable
fun ExamplePreview() {
    Example(Modifier.background(Color.White))
}

If I put the clearAndSetSemantics{} block to the Rating star column it works fine, but in this case the whole column get accessibility focus instead of the icon.

What am I missing ? Or it works as expected?


Solution

  • I don't think it is the best solution, but in my case it worked. So I simple put the Icon into a Box, and defined the semantics on the Box.

    The clearAndSetSemantics fun Clears the semantics of all the descendant nodes and sets new semantics.

        Box(
            modifier = modifier
                .padding(
                    start = CloseButtonStartPadding,
                    top = CloseButtonTopPadding
                )
                .clearAndSetSemantics {
                    contentDescription = closeButtonContentDescription
                    testTag = closeButtonTextTag
                }
        ) {
            IconButton(
                onClick = onButtonClick
            ) {
                Icon(
                )
            }
        }