hamibot能否同时find两个元素,哪个先出现就先执行出现元素的相应程序,无限等待到出现其中一个为止。

已存档
090909 · 12 天前
第 1 条补充
·
12 天前

我需要支持页面转换的

第 2 条补充
·
11 天前

如何在ui调用hamibot的.ico图标?有代码例子吗

回答

Hamibot AI
1
· 12 天前

可以。你可以使用 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);
    });

关键点说明:

  1. findOne() 特性findOne() 会无限等待直到控件出现(除非指定超时时间),这正好符合你的"无限等待"需求。

  2. Promise.race():它会等待传入的 Promise 数组中最先完成的那个(无论是成功还是失败),这实现了"哪个先出现就先执行"的逻辑。

  3. 扩展性:你可以轻松添加更多控件查找:

    var selector3 = className('android.widget.Button');
    var promise3 = findElementPromise(selector3);
    Promise.race([promise1, promise2, promise3])...
    
  4. 超时处理:如果需要为每个查找设置超时,可以修改 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();

关键特性:

  1. 持续监控:使用 setInterval 或递归调用实现持续查找
  2. 页面转换支持:可以检测页面变化并执行相应的操作
  3. 灵活性:可以随时添加/移除要监控的元素
  4. 可扩展性:支持复杂的页面工作流

使用建议:

  • 调整 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>
);

说明:

  1. src="https://hamibot.com/icon.png" 指定了Hamibot图标的URL地址
  2. w="100" h="100" 设置控件的宽度和高度为100
  3. radius="20" 设置圆角半径为20,显示为圆角矩形
  4. radius="50" 当半径设置为控件宽高的一半(100/2=50)时,图片会显示为圆形
  5. bg="white" 设置背景色为白色,这样图标显示更清晰

Hamibot会自动缓存网络图片,减少下次加载时间。你也可以下载图标到本地,然后使用 src="file:///sdcard/hamibot_icon.png" 来显示本地图片。

ℹ️ 本回答由 AI 生成,内容仅供参考