hamibot能否同时find两个元素,哪个先出现就先执行出现元素的相应程序,无限等待到出现其中一个为止。
我需要支持页面转换的
如何在ui调用hamibot的.ico图标?有代码例子吗
回答
可以。你可以使用 Promise.any() 配合 findOne() 的异步版本来实现。由于 Hamibot 的 Rhino 引擎不支持 ES2021 的 Promise.any(),我们可以用 Promise.race() 来实现类似效果。
以下是实现代码:
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
// 创建两个控件的查找 Promise
function findElementPromise(selector, timeout) {
return new Promise(function(resolve, reject) {
// 使用 findOne 查找控件,找到后 resolve
var element = selector.findOne(timeout || 0);
if (element) {
resolve({
element: element,
selector: selector
});
} else {
reject(new Error('查找超时'));
}
});
}
// 示例:查找两个不同的控件
var selector1 = id('action_log'); // 日志图标
var selector2 = text('开始'); // 开始按钮
// 创建两个查找 Promise
var promise1 = findElementPromise(selector1);
var promise2 = findElementPromise(selector2);
// 使用 Promise.race 等待最先找到的控件
Promise.race([promise1, promise2])
.then(function(result) {
toastLog('找到控件: ' + result.selector);
// 根据找到的控件执行相应程序
if (result.selector === selector1) {
toastLog('执行日志图标的程序');
result.element.click();
// 这里添加你的程序逻辑
} else if (result.selector === selector2) {
toastLog('执行开始按钮的程序');
result.element.click();
// 这里添加你的程序逻辑
}
})
.catch(function(error) {
toastLog('查找失败: ' + error);
});
关键点说明:
-
findOne()特性:findOne()会无限等待直到控件出现(除非指定超时时间),这正好符合你的"无限等待"需求。 -
Promise.race():它会等待传入的 Promise 数组中最先完成的那个(无论是成功还是失败),这实现了"哪个先出现就先执行"的逻辑。 -
扩展性:你可以轻松添加更多控件查找:
var selector3 = className('android.widget.Button'); var promise3 = findElementPromise(selector3); Promise.race([promise1, promise2, promise3])... -
超时处理:如果需要为每个查找设置超时,可以修改
findElementPromise函数:function findElementPromise(selector, timeout) { return new Promise(function(resolve, reject) { var element = selector.findOne(timeout || 0); // 0 表示无限等待 if (element) { resolve({ element: element, selector: selector }); } else { reject(new Error('查找超时')); } }); }
这种方法能够有效地实现你需要的功能:同时查找多个元素,哪个先出现就执行哪个的相应程序,并且会无限等待直到至少一个元素出现。
补充回答 1
你需要的是支持页面切换(界面变化)的场景,同时查找多个元素,哪个先出现就执行哪个。这种情况下,你需要持续监控而不是只查找一次。
以下是支持页面转换的完整解决方案:
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
// 创建持续监控的函数
function waitForAnyElement(selectors, callback, checkInterval) {
// 检查间隔,默认1000ms
var interval = checkInterval || 1000;
// 创建监控计时器
var timer = setInterval(function() {
// 遍历所有选择器,查找元素
for (var i = 0; i < selectors.length; i++) {
var selector = selectors[i];
var element = selector.findOne(0); // 立即查找,不等待
if (element) {
// 找到元素,清除定时器
clearInterval(timer);
// 执行回调函数,传递元素和对应的选择器
if (callback) {
callback({
element: element,
selector: selector,
selectorIndex: i
});
}
return;
}
}
}, interval);
// 返回timer以便外部可以停止监控
return timer;
}
// 使用示例
function main() {
// 定义要监控的多个元素选择器
var selectors = [
id('btn_login'), // 登录按钮
text('确定'), // 确定按钮
className('android.widget.Button').textContains('下一步'), // 下一步按钮
desc('完成') // 完成按钮
];
// 定义元素找到后的处理函数
function handleElementFound(result) {
toastLog('找到第' + (result.selectorIndex + 1) + '个元素');
// 根据找到的元素执行相应操作
switch(result.selectorIndex) {
case 0: // 登录按钮
toastLog('执行登录流程');
result.element.click();
// 登录后的操作...
break;
case 1: // 确定按钮
toastLog('执行确定操作');
result.element.click();
// 确定后的操作...
break;
case 2: // 下一步按钮
toastLog('执行下一步操作');
result.element.click();
// 下一步后的操作...
break;
case 3: // 完成按钮
toastLog('执行完成操作');
result.element.click();
// 完成后的操作...
break;
}
// 如果需要继续监控其他页面,可以重新启动监控
// setTimeout(function() {
// waitForAnyElement(selectors, handleElementFound);
// }, 2000);
}
// 开始监控
var monitorTimer = waitForAnyElement(selectors, handleElementFound, 500);
// 如果需要设置超时,可以这样做:
// setTimeout(function() {
// clearInterval(monitorTimer);
// toastLog('监控超时,未找到任何元素');
// }, 30000); // 30秒超时
}
// 运行主函数
main();
高级版本:支持页面转换的完整工作流
// 文档地址 https://docs.hamibot.com/
auto.waitFor();
// 页面状态管理器
var PageManager = {
currentPage: null,
// 页面定义
pages: {
'login': {
name: '登录页面',
selectors: [
id('btn_login'),
text('登录')
],
handler: function(element) {
toastLog('在登录页面,执行登录');
element.click();
// 登录操作...
return 'home'; // 返回下一个页面名称
}
},
'home': {
name: '首页',
selectors: [
id('tab_home'),
text('首页')
],
handler: function(element) {
toastLog('在首页,执行操作');
element.click();
return 'detail';
}
},
'detail': {
name: '详情页',
selectors: [
text('详情'),
desc('详细信息')
],
handler: function(element) {
toastLog('在详情页,执行操作');
return null; // 结束流程
}
}
},
// 监控页面转换
monitorPage: function() {
var self = this;
// 查找当前页面
for (var pageName in this.pages) {
var page = this.pages[pageName];
// 检查页面的所有选择器
for (var i = 0; i < page.selectors.length; i++) {
var element = page.selectors[i].findOne(0);
if (element) {
// 找到页面
if (pageName !== this.currentPage) {
toastLog('页面转换到: ' + page.name);
this.currentPage = pageName;
// 执行页面处理函数
var nextPage = page.handler(element);
// 如果有下一个页面,继续监控
if (nextPage) {
setTimeout(function() {
self.monitorPage();
}, 2000);
}
return;
}
}
}
}
// 未找到任何页面,等待后重试
setTimeout(function() {
self.monitorPage();
}, 1000);
},
// 启动页面监控
start: function() {
this.currentPage = null;
this.monitorPage();
}
};
// 使用页面管理器
PageManager.start();
关键特性:
- 持续监控:使用
setInterval或递归调用实现持续查找 - 页面转换支持:可以检测页面变化并执行相应的操作
- 灵活性:可以随时添加/移除要监控的元素
- 可扩展性:支持复杂的页面工作流
使用建议:
- 调整
checkInterval参数控制检查频率(默认1000ms) - 对于快速变化的界面,可以设置为500ms或更短
- 对于性能要求高的场景,可以设置为2000ms或更长
- 使用
clearInterval(timer)在不需要时停止监控
这种方法可以很好地支持页面转换场景,无论页面如何变化,都能监控到目标元素的出现并执行相应程序。
补充回答 2
在UI中调用Hamibot的.ico图标,可以直接使用图片控件(img)并指定图标URL为 https://hamibot.com/icon.png。
以下是代码例子:
// 文档地址 https://docs.hamibot.com/
'ui';
ui.layout(
<vertical>
<text textSize="20sp" textColor="black" margin="10">显示Hamibot图标</text>
<img src="https://hamibot.com/icon.png" w="100" h="100"/>
</vertical>
);
如果你想显示圆角矩形或圆形的Hamibot图标,可以这样:
// 文档地址 https://docs.hamibot.com/
'ui';
ui.layout(
<vertical>
<text textSize="20sp" textColor="black" margin="10">圆角矩形图标</text>
<img w="100" h="100" radius="20" bg="white" src="https://hamibot.com/icon.png" />
<text textSize="20sp" textColor="black" margin="10 0">圆形图标</text>
<img w="100" h="100" radius="50" bg="white" src="https://hamibot.com/icon.png" />
</vertical>
);
说明:
src="https://hamibot.com/icon.png"指定了Hamibot图标的URL地址w="100" h="100"设置控件的宽度和高度为100radius="20"设置圆角半径为20,显示为圆角矩形radius="50"当半径设置为控件宽高的一半(100/2=50)时,图片会显示为圆形bg="white"设置背景色为白色,这样图标显示更清晰
Hamibot会自动缓存网络图片,减少下次加载时间。你也可以下载图标到本地,然后使用 src="file:///sdcard/hamibot_icon.png" 来显示本地图片。