控件遍历与批量操作——find、findOne、findOnce、forEach
四种查找方法
// findOne() — 找第一个匹配,找不到等待,超时抛错(默认 10 秒)
var btn = text("确定").findOne(); // 找不到会等 10 秒然后抛异常
// findOne(timeout) — 自定义等待时间
var btn = text("确定").findOne(3000); // 最多等 3 秒
// findOnce() — 立即查找,不等待,找不到返回 null
var btn = text("确定").findOnce(); // 没找到就是 null
if (btn) btn.click();
// find() — 返回所有匹配的数组(UiCollection)
var allBtns = className("Button").find();
log("共找到 " + allBtns.length + " 个按钮");
遍历操作
// forEach 批量操作
className("Button").find().forEach(function(btn) {
log("按钮:" + btn.text());
// 注意:在 forEach 里直接 click 所有按钮可能不是你想要的行为
});
// map 收集结果
var titles = className("TextView").find().map(function(tv) {
return tv.text();
});
log(titles.join(", ")); // 所有文本拼接
// some / every 判断
var hasConfirm = className("Button").find().some(function(btn) {
return btn.text() == "确定";
});
控件操作方法
找到控件后(UiObject)可以执行:
var btn = text("签到").findOne();
// 基本操作
btn.click(); // 点击
btn.longClick(); // 长按
btn.clickable(false).click(); // 即使不可点击也硬点
// 读取属性
btn.text(); // 文本
btn.id(); // ID
btn.bounds(); // {left, top, right, bottom}
btn.enabled(); // 是否可用
btn.visible(); // 是否可见
// 获取坐标再用坐标操作
var b = btn.bounds();
click(b.centerX(), b.centerY()); // 点击中心点
错误处理
找不到控件时的三种处理方式:
// 方式一:findOnce + if 判断
var btn = text("签到").findOnce();
if (btn) {
btn.click();
} else {
log("签到按钮不存在,跳过");
}
// 方式二:findOne + timeout
try {
text("签到").findOne(3000).click();
} catch (e) {
log("3 秒内没出现签到按钮:" + e);
}
// 方式三:waitIf
auto.waitFor(); // 等无障碍
text("签到").waitFor(5000).click(); // 智能等
实战:处理商品列表
// 找到页面上所有商品卡片(假设每个卡片是一个 RecyclerView 子项)
var cards = className("android.widget.FrameLayout")
.bounds(0, 400, 1080, 2400)
.find();
log("发现 " + cards.length + " 个商品卡片");
// 遍历,只点击价格低于 100 的
cards.forEach(function(card) {
var priceText = card.findOne(textMatches("¥\\d+"));
if (priceText) {
var price = parseFloat(priceText.text().replace("¥", ""));
if (price < 100) {
log("低价商品:" + priceText.text());
// card.click();
}
}
});