Accessibility related question I am working on a mobility app in which we have a `Column` listing ne...
c
Accessibility related question I am working on a mobility app in which we have a
Column
listing nearby Stops. These Stop items show which Lines stop there. When Talkback reaches the Lines, I want it to add a prefix before starting to read out the line numbers which says “Departs from here: ” and then the line numbers, so in the screenshot it would read the name of the stop, then the distance from the stop and then: “Departs form here: bus 231, night bus 973, night bus 996, night bus 996A” Currently I am adding a 1x1 Spacer before the Green box (which is a Column in my code) with the
contentDescription
set to “Departs from here: ” but it feels like a nasty hack. Is there a better way to add a prefix to a group of elements?
j
You could use clearAndSetSemantics
c
Yeah, but then I am clearing everything that my inner elements (the line numbers) would read out. I want to keep that. Since these are elements that we are sharing in multiple places, I would not like to build up the string myself, because if the element is changing how it constructs its own contentDescription, then I would need to change it here also
So I would like something like: get the contentDescription of my descendants, and add a prefix to that
j
Got it. Had a similar use case once. I think thats not possible - but not sure.
c
Yeah, unfortunately I was not able to do this, but thought it might worth asking. Seems like a pretty common task
d
Given we are going with hacky solutions - you could check if screen reader is turned on and add a text composable if yes. Then UI will stay the same for non-screen reader users and for the ones with screen reader on it will nicely let them swipe to read that text and then the numbers
a
Your solution seems totally valid. You want some hidden semantics so you have to use some invisible elements or rebuild the semantics yourself. Why do you feel it nasty?
If there's a, say, modifier to add a prefix to the semantics, should there be modifier to add a suffix or to insert something into the middle of the semantics?
c
@Albert Chang The main problem is that, my extra element is not even invisible, it is 1x1 dp in size, because invisible elements are not read by TalkBack. My main problem with providing my own
contentDescription
is that I did not find a way to evaluate what the system would assign as the default
contentDescription
that I could alter myself. In the good old View world we were iterating over the child Views, getting their contentDescriptions, appending them and then we had it. Should I do the same here?
a
You can just use
Copy code
Modifier.semantics(mergeDescendants = true) {
    contentDescription = "Departs from here"
}
on the parent as the semantics of the parent come before the children when merged.
If want to build the semantics yourself, just use the same ui state as what you use to render the UI since that's the single source of truth. This is how things work in a declarative UI toolkit.
c
What you say about using mergeDescendants together with contentDescription is true, the contentDescription of the parent comes before its children, but using
mergeDescendants
on the parent makes it a standalone item for TalkBack, so now the user has to manually change the focus in order to read out what is inside it.
It is true that you can build your own semantics, but if you have children that customize their contentDescription it can be hard to maintain your custom semantics, and remember to update it whenever you change your content
Thats why it would be nice to retrieve the “original” merged contentDescription of the children and append a prefix before it.
a
using mergeDescendants on the parent makes it a standalone item for TalkBack
In that case, as I said before, use invisible element or rebuild the semantics yourself.
remember to update it whenever you change your content
You don't update the semantics in a declarative UI toolkit. You declare it. That's the whole point of "declarative".
Thats why it would be nice to retrieve the “original” merged contentDescription of the children
Iterating through children is intentionally prohibited in compose's design.
c
Sorry, by updating it I meant updating the code that is responsible for creating the semantics
So that way If I change my child Composables, I would need to update the parent separately
I am going with adding an “invisible” element for now as I don’t have any other idea to solve this. Thank you for the suggestions!