弹出框窗口控件有时候调用click不生效,只有在强制sleep一定时间后点击事件才生效
目前遇到一个问题:弹出框窗口控件有时候调用click不生效,只有在强制sleep一定时间后点击事件才生效。
wait(() => {
toastLog("判断控件是否出现");
return textContains(text).exists() &&
textContains(text).findOne().bounds().width() > 0 &&
textContains(text).clickable();
},300,30);
textContains(text).waitFor();
if (actionText) toastLog(actionText);
var element;
element = textContains(text).findOne();
click(element.bounds().centerX(), element.bounds().centerY());
toastLog("判断控件是否出现")打印正常,但点击(click)方法点击不生效,除非在click方法调用之前假如sleep(someTime)才生效,请教下有可能是什么原因导致,
我也碰到了,排查了很久,是因为控件开始时clickable=false,所以点击了,但是无效。不知道算不算bug。 现在在控件中追加clickable().findOne(time)来确保clickable=true或者用pickup获取正确控件。
Cross referenced this in issue #352 by SuperMonster003 on Apr 9, 2025.
控件的出现有时不是 "闪现", 而是通过动画过度出现 (例如从屏幕底部滑动出现). 此时控件的属性 (如 bounds) 是不断变化的.
click(x, y) 点击坐标的方式, 可能点击到的位置是控件首次被捕获到的位置, 而并非最终位置, 因此无法达到预期的点击效果.
一个可能的方案是使用 UiObject#click 方法, 如 xxx.findOnce().click(), 控件被定位之后, 不论它是否出现位置变化, 都可以对目标进行点击操作 (不依赖坐标), 但需要确保它的 clickable 属性为 true, 或者在某些情况下, 它的 [一级/二级/三级...] 父控件 clickable 为 true 时也可以通过点击父控件实现点击效果 (依然是使用 UiObject#click 方法.
如果你习惯使用 pickup, 也可以直接使用下面这样的示例方法:
pickup({
textContains: text,
minWidth: 1,
}, 'k2', 'click');
其中 k2 表示向上遍历可点击父控件的级别限制, 通常可以尝试从 k0 依次增加到 k4, 并在每次增加时实际测试点击效果 (也可以通过布局分析工具查看具体哪一级父控件是可点击的).
另外, 不推荐多次使用相同或类似的 UiSelector 查找控件, 这样有一定概率无法获取到之前本已经找到的相同控件.
例如:
if (text('foo').exists()) {
console.log(text('foo').findOnce().bounds());
}
上述代码使用了两次查找, 第一次为判断存在, 这个过程中相当于对控件进行了查找, 而 findOnce 又对控件进行了一次新的查找, 此时不一定会找得到符合条件的控件 (例如恰好第二次查找的时候控件消失).
比较保险的做法是将第一次找到的控件缓存下来.
let widget = text('foo').findOnce();
if (widget !== null) {
console.log(widget.bounds());
}
最后, wait 中不建议在条件中加入阻塞式条件判断 (findOne 即为阻塞函数), 可以参考一下 wait 的文档.
Cross referenced this in issue #352 by SuperMonster003 on Apr 9, 2025.
控件的出现有时不是 "闪现", 而是通过动画过度出现 (例如从屏幕底部滑动出现). 此时控件的属性 (如
bounds) 是不断变化的.
click(x, y)点击坐标的方式, 可能点击到的位置是控件首次被捕获到的位置, 而并非最终位置, 因此无法达到预期的点击效果.一个可能的方案是使用
UiObject#click方法, 如xxx.findOnce().click(), 控件被定位之后, 不论它是否出现位置变化, 都可以对目标进行点击操作 (不依赖坐标), 但需要确保它的clickable属性为true, 或者在某些情况下, 它的 [一级/二级/三级...] 父控件clickable为true时也可以通过点击父控件实现点击效果 (依然是使用UiObject#click方法.如果你习惯使用 pickup, 也可以直接使用下面这样的示例方法:
pickup({ textContains: text, minWidth: 1, }, 'k2', 'click'); 其中
k2表示向上遍历可点击父控件的级别限制, 通常可以尝试从k0依次增加到k4, 并在每次增加时实际测试点击效果 (也可以通过布局分析工具查看具体哪一级父控件是可点击的).另外, 不推荐多次使用相同或类似的
UiSelector查找控件, 这样有一定概率无法获取到之前本已经找到的相同控件.例如:
if (text('foo').exists()) { console.log(text('foo').findOnce().bounds()); } 上述代码使用了两次查找, 第一次为判断存在, 这个过程中相当于对控件进行了查找, 而
findOnce又对控件进行了一次新的查找, 此时不一定会找得到符合条件的控件 (例如恰好第二次查找的时候控件消失).比较保险的做法是将第一次找到的控件缓存下来.
let widget = text('foo').findOnce(); if (widget !== null) { console.log(widget.bounds()); } 最后,
wait中不建议在条件中加入阻塞式条件判断 (findOne即为阻塞函数), 可以参考一下wait的文档.
感谢解答,目前我测试是在某些特定的场景下会出来控件的clickable属性获取异常的情况,以下是100%复现场景: 中国银行app-登陆后点击-我的-我的游戏-弹出福仔云游记页面-右侧天天签到浮框-即text('d2d3efbff6a1d588574e')的clickable始终是false,切换页面后才能获取到true值,此时才可点击。不知道算不算bug。
使用中国银行手机客户端 v9.0.7, 找到目标控件, 但未能复现 "clickable 始终是 false, 切换页面后才能获取到 true 值" 现象.
wait('d2d3efbff6a1d588574e', {
then(w) {
toastlog(w.clickable());
},
else() {
toastwarn('Not found');
},
});
运行代码后, 短时间内进入页面, 会在第一次定位到目标控件后得到 true 结果. 这表明首次定位到的目标控件, 就已经是 clickable=true 的状态了.
在你描述的现象成立的前提下, 如果控件可以在一定时间内自行变换到 clickable=true 状态, 则可以通过微调上述代码来时间自动监测其点击状态:
wait({
content: 'd2d3efbff6a1d588574e',
clickable: true,
}, {
then(w) {
toastlog(w);
},
else() {
toastwarn('Not found');
},
});
以下截图为我测试后获取到的控件摘要:
如果控件不能自动变为 clickable=true 状态, 而是需要重新进入页面或其他方式刷新页面控件时, 可点击状态才变更为正常状态, 则可采取以下措施 (仅供参考).
在合适的时机尝试使用 auto.clearCache(), 或者在目标控件可点击状态为 false 时, 查看其布局中父控件 (或多级父控件) 的可点击状态, 并尝试使用 UiObject#click 方法测试效果. 最后, 如果没有任何可行方案, 则可利用 automator.click 方法 (可全局访问):
- click(bounds: android.graphics.Rect)
- click(widget: UiObject)
- click(x: number, y: number)
- ... ...
当然 UiObject#clickBounds 也可以达到同样的效果.
不论使用哪种方式成功点击了目标控件, 对于点击后的条件检测 (如新控件的出现, 旧控件的消失, 关键控件的属性变化等) 在某些条件下还是十分必要的, 这样可以一定程度上保证点击动作是成功的, 也可以在点击失败后进行 fallback 措施或通过不同渠道将失败消息通知给脚本用户.
使用中国银行手机客户端 v9.0.7, 找到目标控件, 但未能复现 "clickable 始终是 false, 切换页面后才能获取到 true 值" 现象.
wait('d2d3efbff6a1d588574e', { then(w) { toastlog(w.clickable()); }, else() { toastwarn('Not found'); }, }); 运行代码后, 短时间内进入页面, 会在第一次定位到目标控件后得到
true结果. 这表明首次定位到的目标控件, 就已经是clickable=true的状态了.在你描述的现象成立的前提下, 如果控件可以在一定时间内自行变换到
clickable=true状态, 则可以通过微调上述代码来时间自动监测其点击状态:wait({ content: 'd2d3efbff6a1d588574e', clickable: true, }, { then(w) { toastlog(w); }, else() { toastwarn('Not found'); }, }); 以下截图为我测试后获取到的控件摘要:
如果控件不能自动变为
clickable=true状态, 而是需要重新进入页面或其他方式刷新页面控件时, 可点击状态才变更为正常状态, 则可采取以下措施 (仅供参考).在合适的时机尝试使用
auto.clearCache(), 或者在目标控件可点击状态为false时, 查看其布局中父控件 (或多级父控件) 的可点击状态, 并尝试使用UiObject#click方法测试效果. 最后, 如果没有任何可行方案, 则可利用automator.click方法 (可全局访问):
- click(bounds: android.graphics.Rect)
- click(widget: UiObject)
- click(x: number, y: number)
- ... ...
当然
UiObject#clickBounds也可以达到同样的效果.不论使用哪种方式成功点击了目标控件, 对于点击后的条件检测 (如新控件的出现, 旧控件的消失, 关键控件的属性变化等) 在某些条件下还是十分必要的, 这样可以一定程度上保证点击动作是成功的, 也可以在点击失败后进行 fallback 措施或通过不同渠道将失败消息通知给脚本用户.
我重新进行了测试,发现是指纹解锁(屏下指纹)进行了干扰。 测试代码: launchApp("中国银行"); sleep(10000) wait({ content: 'd2d3efbff6a1d588574e', clickable: true, }, { then(w) { toastlog(w); }, else() { toastwarn('Not found'); }, }); 在以上代码执行中只要激活了指纹验证(即使关闭后用手势解锁),就找不到控件。 我的手机是iqoo neo10,指纹解锁验证界面时autojs6的悬浮窗口也无法点击,系统下滑页面也无法下滑。我觉得这是系统问题,和js6无关,抱歉耽误大佬时间了。
@wingswing1
这样的情况似乎没办法做特殊兼容了, 系统级的一些设置, 确实会影响 AutoJs6 的一些功能, 例如安卓系统的设置页面可以拥有最高级别的顶层显示权限, 甚至位于 AutoJs6 的浮动窗口和浮动按钮之上, 此时与之相关的操作和功能可能都会受到影响.
如有其他问题, 欢迎继续反馈.