Skip to content

Commit 2a5a5f3

Browse files
committed
feat(assists): 优化元素查找功能并添加新特性
- 扩展 findById、findByText等方法支持多条件过滤- 新增 filterNodes 方法统一处理节点过滤逻辑 - 添加 getAllNodes 方法支持获取当前窗口所有节点并进行过滤 - 为 AccessibilityNodeInfo 类增加 getBoundsInParent 方法 - 添加 nodeGestureClickByDouble 方法实现双击操作 - 新增 isVisible 方法判断节点是否可见
1 parent 96a6926 commit 2a5a5f3

File tree

1 file changed

+137
-39
lines changed

1 file changed

+137
-39
lines changed

assists/src/main/java/com/ven/assists/AssistsCore.kt

Lines changed: 137 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -153,72 +153,103 @@ object AssistsCore {
153153
* @param text 可选的文本过滤条件
154154
* @return 符合条件的元素列表
155155
*/
156-
fun findById(id: String, text: String? = null): List<AccessibilityNodeInfo> {
157-
var nodeInfos = AssistsService.instance?.rootInActiveWindow?.findById(id) ?: arrayListOf()
158-
159-
nodeInfos = text?.let {
160-
nodeInfos.filter {
161-
if (it.txt() == text) {
162-
return@filter true
163-
}
164-
return@filter false
165-
}
166-
} ?: let { nodeInfos }
167-
168-
return nodeInfos
156+
fun findById(id: String, filterText: String? = null, filterDes: String? = null, filterClass: String? = null): List<AccessibilityNodeInfo> {
157+
var nodes = AssistsService.instance?.rootInActiveWindow?.findById(id) ?: arrayListOf()
158+
val filterNodes = filterNodes(nodes, filterText = filterText, filterDes = filterDes, filterClass = filterClass)
159+
return filterNodes
169160
}
170161

171162
/**
172163
* 在指定元素范围内通过id查找所有符合条件的元素
173164
* @param id 元素的资源id
174165
* @return 符合条件的元素列表
175166
*/
176-
fun AccessibilityNodeInfo?.findById(id: String): List<AccessibilityNodeInfo> {
177-
if (this == null) return arrayListOf()
178-
findAccessibilityNodeInfosByViewId(id)?.let {
179-
return it
180-
}
181-
return arrayListOf()
167+
fun AccessibilityNodeInfo?.findById(
168+
id: String,
169+
filterText: String? = null,
170+
filterDes: String? = null,
171+
filterClass: String? = null
172+
): List<AccessibilityNodeInfo> {
173+
val nodes = this?.findAccessibilityNodeInfosByViewId(id) ?: arrayListOf()
174+
val filterNodes = filterNodes(nodes, filterText = filterText, filterDes = filterDes, filterClass = filterClass)
175+
return filterNodes
182176
}
183177

184178
/**
185179
* 通过文本内容查找所有符合条件的元素
186180
* @param text 要查找的文本内容
187181
* @return 符合条件的元素列表
188182
*/
189-
fun findByText(text: String): List<AccessibilityNodeInfo> {
190-
return AssistsService.instance?.rootInActiveWindow?.findByText(text) ?: arrayListOf()
183+
fun findByText(text: String, filterViewId: String? = null, filterDes: String? = null, filterClass: String? = null): List<AccessibilityNodeInfo> {
184+
val nodes = AssistsService.instance?.rootInActiveWindow?.findByText(text) ?: arrayListOf()
185+
val filterNodes = filterNodes(nodes, filterViewId = filterViewId, filterDes = filterDes, filterClass = filterClass)
186+
return filterNodes
191187
}
192188

193189
/**
194190
* 查找所有文本完全匹配的元素
195191
* @param text 要匹配的文本内容
196192
* @return 文本完全匹配的元素列表
197193
*/
198-
fun findByTextAllMatch(text: String): List<AccessibilityNodeInfo> {
199-
val listResult = arrayListOf<AccessibilityNodeInfo>()
200-
val list = AssistsService.instance?.rootInActiveWindow?.findByText(text)
201-
list?.let {
202-
it.forEach {
203-
if (TextUtils.equals(it.text, text)) {
204-
listResult.add(it)
205-
}
206-
}
207-
}
208-
return listResult
194+
fun findByTextAllMatch(
195+
text: String,
196+
filterViewId: String? = null,
197+
filterDes: String? = null,
198+
filterClass: String? = null
199+
): List<AccessibilityNodeInfo> {
200+
val nodes = AssistsService.instance?.rootInActiveWindow?.findByText(text) ?: arrayListOf()
201+
val filterNodes = filterNodes(nodes, filterViewId = filterViewId, filterDes = filterDes, filterClass = filterClass)
202+
return filterNodes
209203
}
210204

211205
/**
212206
* 在指定元素范围内通过文本查找所有符合条件的元素
213207
* @param text 要查找的文本内容
214208
* @return 符合条件的元素列表
215209
*/
216-
fun AccessibilityNodeInfo?.findByText(text: String): List<AccessibilityNodeInfo> {
217-
if (this == null) return arrayListOf()
218-
findAccessibilityNodeInfosByText(text)?.let {
219-
return it
210+
fun AccessibilityNodeInfo?.findByText(
211+
text: String,
212+
filterViewId: String? = null,
213+
filterDes: String? = null,
214+
filterClass: String? = null
215+
): List<AccessibilityNodeInfo> {
216+
217+
val nodes = this?.findAccessibilityNodeInfosByText(text) ?: arrayListOf()
218+
219+
val filterNodes = filterNodes(nodes, filterViewId = filterViewId, filterDes = filterDes, filterClass = filterClass)
220+
return filterNodes
221+
}
222+
223+
224+
private fun filterNodes(
225+
nodes: List<AccessibilityNodeInfo>,
226+
filterViewId: String? = null,
227+
filterDes: String? = null,
228+
filterClass: String? = null,
229+
filterText: String? = null
230+
): List<AccessibilityNodeInfo> {
231+
val filterNodes = nodes.filter { node ->
232+
233+
filterViewId?.let {
234+
if (it.isEmpty()) return@let
235+
return@filter node.viewIdResourceName?.equals(filterViewId) == true
236+
}
237+
filterText?.let {
238+
if (it.isEmpty()) return@let
239+
return@filter node.text?.toString()?.equals(filterText) == true
240+
}
241+
filterDes?.let {
242+
if (it.isEmpty()) return@let
243+
return@filter node.contentDescription?.toString()?.equals(filterDes) == true
244+
}
245+
filterClass?.let {
246+
if (it.isEmpty()) return@let
247+
return@filter node.className?.toString()?.equals(filterClass) == true
248+
}
249+
250+
true
220251
}
221-
return arrayListOf()
252+
return filterNodes
222253
}
223254

224255
/**
@@ -383,10 +414,16 @@ object AssistsCore {
383414
* 获取当前窗口中的所有元素
384415
* @return 包含所有元素的列表
385416
*/
386-
fun getAllNodes(): ArrayList<AccessibilityNodeInfo> {
417+
fun getAllNodes(
418+
filterViewId: String? = null,
419+
filterDes: String? = null,
420+
filterClass: String? = null,
421+
filterText: String? = null
422+
): List<AccessibilityNodeInfo> {
387423
val nodeList = arrayListOf<AccessibilityNodeInfo>()
388424
AssistsService.instance?.rootInActiveWindow?.getNodes(nodeList)
389-
return nodeList
425+
val filterNodes = filterNodes(nodeList, filterViewId, filterDes, filterClass, filterText)
426+
return filterNodes
390427
}
391428

392429
/**
@@ -546,6 +583,12 @@ object AssistsCore {
546583
return boundsInScreen
547584
}
548585

586+
fun AccessibilityNodeInfo.getBoundsInParent(): Rect {
587+
val rect = Rect()
588+
getBoundsInParent(rect)
589+
return rect
590+
}
591+
549592
/**
550593
* 点击元素
551594
* @return 点击操作是否成功
@@ -609,6 +652,61 @@ object AssistsCore {
609652
return result
610653
}
611654

655+
suspend fun AccessibilityNodeInfo.nodeGestureClickByDouble(
656+
offsetX: Float = ScreenUtils.getScreenWidth() * 0.01953f,
657+
offsetY: Float = ScreenUtils.getScreenWidth() * 0.01953f,
658+
switchWindowIntervalDelay: Long = 250,
659+
clickDuration: Long = 25,
660+
clickInterval: Long = 25,
661+
): Boolean {
662+
AssistsWindowManager.nonTouchableByAll()
663+
delay(switchWindowIntervalDelay)
664+
val bounds = getBoundsInScreen()
665+
666+
val x = bounds.centerX().toFloat() + offsetX
667+
val y = bounds.centerY().toFloat() + offsetY
668+
669+
AssistsCore.gestureClick(x, y, clickDuration)
670+
delay(clickInterval)
671+
AssistsCore.gestureClick(x, y, clickDuration)
672+
AssistsWindowManager.touchableByAll()
673+
return true
674+
}
675+
676+
fun AccessibilityNodeInfo.isVisible(
677+
compareNode: AccessibilityNodeInfo? = null,
678+
isFullyByCompareNode: Boolean = false,
679+
): Boolean {
680+
compareNode?.let {
681+
682+
if (!isVisibleToUser) return@let false
683+
684+
val compareNodeBounds = it.getBoundsInScreen()
685+
val nodeBounds = getBoundsInScreen()
686+
if (isFullyByCompareNode) {
687+
688+
if (compareNodeBounds.contains(nodeBounds)) {
689+
return false
690+
}
691+
if (Rect.intersects(compareNodeBounds, nodeBounds)) {
692+
return false
693+
}
694+
return true
695+
696+
} else {
697+
698+
if (compareNodeBounds.contains(nodeBounds)) {
699+
return false
700+
}
701+
702+
return true
703+
704+
}
705+
706+
}
707+
return isVisibleToUser
708+
}
709+
612710
/**
613711
* 执行返回操作
614712
* @return 返回操作是否成功

0 commit comments

Comments
 (0)