-
Notifications
You must be signed in to change notification settings - Fork 2
/
AccessibilityNodeInfo.kt
92 lines (83 loc) · 2.89 KB
/
AccessibilityNodeInfo.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package androidx.core.view.accessibility
import android.graphics.Rect
import android.util.Log
import android.view.accessibility.AccessibilityNodeInfo
import androidx.compose.ui.graphics.toComposeRect
fun AccessibilityNodeInfo.getRect(): Rect {
val r = Rect()
this.getBoundsInScreen(r)
return r
}
@Suppress("SpellCheckingInspection")
fun scanInteractableAccessibilityNodeInfo(
root: AccessibilityNodeInfo,
enabled: Boolean = true,
): List<Pair<AccessibilityNodeInfo, androidx.compose.ui.geometry.Rect>> {
val accumulatingResult =
mutableListOf<Pair<AccessibilityNodeInfo, androidx.compose.ui.geometry.Rect>>()
scanInteractableAccessibilityNodeInfo(accumulatingResult, root, 0) { nodeInfo ->
nodeInfo.isEnabled == enabled
&& (nodeInfo.isClickable
|| nodeInfo.isFocusable
|| nodeInfo.isCheckable
|| nodeInfo.isDismissable
)
&& nodeInfo.isVisibleToUser
}
return accumulatingResult.toList()
}
@Suppress("SpellCheckingInspection")
private fun scanInteractableAccessibilityNodeInfo(
accumulatingList: MutableList<Pair<AccessibilityNodeInfo, androidx.compose.ui.geometry.Rect>>,
nodeInfo: AccessibilityNodeInfo?,
depth: Int,
filteringCondition: (AccessibilityNodeInfo) -> Boolean = { true },
) {
if (nodeInfo == null) return
if (filteringCondition(nodeInfo)) {
accumulatingList.add(nodeInfo to nodeInfo.getRect().toComposeRect())
}
for (index in 0 until nodeInfo.childCount) {
scanInteractableAccessibilityNodeInfo(
accumulatingList, nodeInfo.getChild(index), depth + 1, filteringCondition
)
}
}
@Deprecated("For logcat debug purpose")
fun logNodeHierarchy(nodeInfo: AccessibilityNodeInfo?, depth: Int, tag: String) {
if (nodeInfo == null) return
if (nodeInfo.isEnabled && (nodeInfo.isClickable || nodeInfo.isFocusable || nodeInfo.isCheckable || nodeInfo.isDismissable)) {
val b = if (depth == 0) "" else "|"
val c = b + "-".repeat(depth)
val r = Rect()
r.toComposeRect()
nodeInfo.getBoundsInScreen(r)
val s = getText(nodeInfo)
val logString = "${c}$s\n(x=${r.left}, y=${r.top}, w=${r.width()}, h=${r.height()}) "
"${nodeInfo.actionList}"
Log.v(tag, logString)
}
for (i in 0 until nodeInfo.childCount) {
@Suppress("DEPRECATION")
(logNodeHierarchy(
nodeInfo.getChild(i),
depth + 1,
tag
))
}
}
private fun getText(nodeInfo: AccessibilityNodeInfo): String {
val a = buildString {
append(nodeInfo.text ?: "")
nodeInfo.contentDescription?.let { append("-$it") }
}
if (a.isBlank()) {
for (i in 0 until nodeInfo.childCount) {
val b = getText(nodeInfo.getChild(0))
if (b.isNotBlank()) {
return b
}
}
}
return a
}