UiSelector 选择器 API 核心 — 控件定位的基石
什么是选择器
选择器(UiSelector)是 AutoJs6 定位屏幕控件的核心机制。它根据控件的属性(id、text、desc、className 等)筛选出你想要操作的控件,类似网页开发中的 CSS 选择器。
屏幕上的控件树:
┌──────────────────────────────┐
│ [TextView] "确定" id: btn_ok │ ← text("确定").findOne() 选中它
│ [Button] "取消" │ ← text("取消").findOne() 选中它
│ [EditText] "请输入" id: input│ ← id("input").findOne() 选中它
└──────────────────────────────┘
基本匹配属性
id — 最精确的定位方式
android:id 是 Android 控件的唯一标识,首选用 id 定位。
// 精确匹配
let btnOk = id("btn_ok").findOne();
// 包含匹配
let inputAny = idContains("input").findOne();
// 正则匹配(v6.7 新增)
let dynamicBtn = idMatches(/btn_\d+/).findOne();
text — 控件显示的文字
// 精确匹配
text("登录").click();
// 包含匹配
textContains("登录").click();
// 正则匹配(v6.7 支持标志位)
textMatches(/登\s*录/i).click();
// 以...开头/结尾
textStartsWith("确").click();
textEndsWith("定").click();
desc — 内容描述(无障碍描述)
部分应用不给控件设置 id 和 text,但会设置 content-description。
// 和 text 用法一样
desc("返回").click();
descContains("设置").click();
descMatches(/\d+%/).click();
className — 控件类型
// 按控件类型筛选
className("Button").findOne();
className("EditText").findOne();
// 常见 Android 控件类型
// TextView, EditText, Button, ImageView, ImageButton, CheckBox,
// Switch, RadioButton, ToggleButton, SeekBar, ProgressBar,
// ScrollView, RecyclerView, LinearLayout, FrameLayout, ConstraintLayout 等
其他匹配属性
| 方法 | 说明 | 示例 |
|---|---|---|
clickable(b) | 是否可点击 | clickable(true).findOne() |
focusable(b) | 是否可聚焦 | focusable(true) |
visibleToUser(b) | 是否对用户可见 | visibleToUser(true) |
enabled(b) | 是否启用 | enabled(true) |
editable(b) | 是否可编辑 | editable(true) |
selected(b) | 是否被选中 | selected(true) |
checked(b) | 是否被勾选 | checked(true) |
scrollable(b) | 是否可滚动 | scrollable(true) |
index(i) | 在父控件中的索引 | index(0) |
depth(d) | 在控件树中的深度 | depth(5) |
bounds — 坐标范围
// bounds 是 Rect 对象,四个值:left, top, right, bottom
// 返回控件的屏幕坐标范围
// boundsInside — 选择完全在指定区域内的控件
let controls = boundsInside(0, 1000, 1080, 1500).find();
// bounds — 精确坐标匹配
let target = bounds(0, 0, 1080, 100).findOne();
// boundsContains — 包含指定点
let point = boundsContains(500, 800).findOne();
组合多个条件
通过链式调用组合多个匹配条件,条件之间是 AND(与) 的关系:
// 找一个 id 是 btn_ 开头、文字包含"确定"、可点击的 Button
let button = idContains("btn_")
.textContains("确定")
.clickable(true)
.className("Button")
.findOne();
if (button) {
button.click();
}
同一属性多次调用 = AND
// 这个条件要求 className 既是 Button 又是 TextView
// 实际没有控件同时满足,返回 null
className("Button").className("TextView").findOne(); // null
查找方法
findOne — 找第一个匹配
// 无超时(默认 10 秒)
let control = id("btn_ok").findOne();
// 指定超时(毫秒)
let control = id("btn_ok").findOne(5000); // 最多等 5 秒
// 找不到返回 null,不是抛异常!
let control = text("不存在的文字").findOne(1000);
console.log(control); // null
if (control) {
control.click(); // 必须先判空再操作
}
find — 找所有匹配
// 返回 UiObject 数组(可能为空数组)
let buttons = className("Button").find();
console.log("找到 " + buttons.length + " 个 Button");
// 遍历所有按钮
buttons.forEach(btn => {
console.log("按钮文字: " + btn.text());
});
findOnce — 立即查找
// 和 findOne 一样,但不会等待超时,立即返回
let control = id("btn_ok").findOnce();
if (control) {
control.click();
} else {
console.log("没找到,可能还没加载好");
}
exists — 仅判断是否存在
// 返回 true / false,不返回控件对象
if (text("确定").exists()) {
text("确定").findOne().click();
}
// exists 也接受超时参数
if (id("loading").exists(3000)) {
// 3 秒内 loading 都没消失,可能加载异常
}
waitFor — 等待控件出现
// 等待匹配的控件出现,默认 10 秒
text("确定").waitFor();
// 指定超时
id("login_btn").waitFor(5000);
// 等控件消失
id("loading").waitUntilGone(3000);
选择器优先级建议
1. id() → 最优先,精确且稳定
2. text() / desc() → 次优先,人类可读
3. className() + bounds() → 补充定位
4. clickable() / visibleToUser() → 过滤干扰
避免:仅靠 className() 定位,同类控件太多容易选错。