@@ -94,9 +94,9 @@ public class AccessibilityRenderExtension : RenderExtension {
9494
9595 private fun View.processAccessibleChildren (processElement : (AccessibilityElement ) -> Unit ) {
9696 val accessibilityText = this .accessibilityText()
97- if (isImportantForAccessibility && ! accessibilityText.isNullOrBlank() && isVisible) {
98- val bounds = Rect ().also (::getBoundsOnScreen)
97+ val bounds = Rect ().also (::getBoundsOnScreen)
9998
99+ if (isImportantForAccessibility && ! accessibilityText.isNullOrBlank() && isVisible) {
100100 processElement(
101101 AccessibilityElement (
102102 id = " ${this ::class .simpleName} ($accessibilityText )" ,
@@ -111,9 +111,18 @@ public class AccessibilityRenderExtension : RenderExtension {
111111 val viewRoot = getChildAt(0 ) as ViewRootForTest
112112 val unmergedNodes = viewRoot.semanticsOwner.getAllSemanticsNodes(false )
113113
114+ // SemanticsNode.boundsInScreen isn't reported correctly for nodes so locationOnScreen used to correctly calculate displayBounds.
115+ val locationOnScreen = arrayOf(bounds.left, bounds.top).toIntArray()
116+ locationOnScreen[0 ] + = paddingLeft
117+ locationOnScreen[1 ] + = paddingTop
114118 val orderedSemanticsNodes = viewRoot.semanticsOwner.rootSemanticsNode.orderSemanticsNodeGroup()
115119 orderedSemanticsNodes.forEach {
116- it.processAccessibleChildren(processElement, unmergedNodes)
120+ it.processAccessibleChildren(
121+ processElement = processElement,
122+ locationOnScreen = locationOnScreen,
123+ viewBounds = bounds,
124+ unmergedNodes = unmergedNodes
125+ )
117126 }
118127 }
119128
@@ -173,6 +182,8 @@ public class AccessibilityRenderExtension : RenderExtension {
173182
174183 private fun SemanticsNode.processAccessibleChildren (
175184 processElement : (AccessibilityElement ) -> Unit ,
185+ locationOnScreen : IntArray ,
186+ viewBounds : Rect ,
176187 unmergedNodes : List <SemanticsNode >?
177188 ) {
178189 val accessibilityText = if (config.isMergingSemanticsOfDescendants) {
@@ -188,9 +199,14 @@ public class AccessibilityRenderExtension : RenderExtension {
188199 }
189200
190201 if (accessibilityText != null ) {
191- val displayBounds = with (boundsInWindow) {
192- Rect (left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
202+ // SemanticsNode.boundsInScreen isn't reported correctly for nodes so boundsInRoot + locationOnScreen used to correctly calculate displayBounds.
203+ val displayBounds = with (boundsInRoot) {
204+ Rect (left.toInt(), top.toInt(), right.toInt(), bottom.toInt()).run {
205+ offset(locationOnScreen[0 ], locationOnScreen[1 ])
206+ Rect (left, top, right.coerceIn(0 , viewBounds.right), bottom.coerceIn(0 , viewBounds.bottom))
207+ }
193208 }
209+
194210 processElement(
195211 AccessibilityElement (
196212 // SemanticsNode.id is backed by AtomicInteger and is not guaranteed consistent across runs.
@@ -200,6 +216,15 @@ public class AccessibilityRenderExtension : RenderExtension {
200216 )
201217 )
202218 }
219+
220+ children.forEach {
221+ it.processAccessibleChildren(
222+ processElement = processElement,
223+ locationOnScreen = locationOnScreen,
224+ viewBounds = viewBounds,
225+ unmergedNodes = unmergedNodes
226+ )
227+ }
203228 }
204229
205230 private fun SemanticsNode.findAllUnmergedNodes (): List <SemanticsNode > {
0 commit comments