Auto.js 入门指南(八)高级控件与 UI 自动化

前言

大家好,我是鲫小鱼。是一名不写前端代码的前端工程师,热衷于分享非前端的知识,带领切图仔逃离切图圈子,欢迎关注我,微信公众号:《鲫小鱼不正经》。欢迎点赞、收藏、关注,一键三连!!

第八章:高级控件与 UI 自动化


一、理论讲解:UI 自动化的核心与难点

在移动端自动化中,UI 控件的识别与操作是最核心也是最具挑战性的部分。高级控件操作不仅仅是简单的点击、输入,还包括复杂的层级遍历、动态控件适配、列表滚动、弹窗处理、表单自动填写、批量操作等。

1.1 高级控件的常见类型

  • 列表(ListView、RecyclerView、ScrollView)
  • 表单(多输入框、下拉框、单选/多选框)
  • 弹窗(Dialog、PopupWindow、Alert)
  • 动态生成控件(如广告、推荐位、动态加载内容)
  • 嵌套布局、复杂层级控件

1.2 UI 自动化的难点

  • 控件层级深、结构复杂,难以唯一定位
  • 动态控件 id/文本/属性经常变化
  • 列表懒加载、分页、滚动加载
  • 弹窗、广告、遮挡层干扰
  • 多语言、多分辨率、多品牌适配

1.3 Auto.js 高级控件操作能力

  • 支持多种查找方式:text、desc、id、className、textMatches、descMatches、bounds、index 等
  • 支持 find、findOne、exists、parent、child、sibling、click、longClick、setText、scrollForward、scrollBackward 等
  • 支持正则、模糊查找、批量操作、属性获取与设置
  • 支持 UI 脚本自定义界面与自动化结合

二、基础用法与进阶代码示例

2.1 列表控件的遍历与操作

javascript 复制代码
// 遍历 ListView 所有项并输出文本
var list = className("android.widget.ListView").findOne();
if (list) {
    for (let i = 0; i < list.childCount(); i++) {
        let item = list.child(i);
        log("第" + (i+1) + "项:" + item.text());
    }
}

// 滚动查找目标项并点击
function scrollAndClick(targetText) {
    var list = className("android.widget.ListView").findOne();
    for (let i = 0; i < 20; i++) {
        let item = text(targetText).findOne(1000);
        if (item) {
            item.click();
            toast("已点击:" + targetText);
            return true;
        }
        list.scrollForward();
        sleep(500);
    }
    toast("未找到目标项");
    return false;
}

2.2 RecyclerView/ScrollView 动态加载

javascript 复制代码
// 滚动 RecyclerView 查找并点击目标
function scrollRecyclerAndClick(targetText) {
    var rv = className("androidx.recyclerview.widget.RecyclerView").findOne();
    for (let i = 0; i < 30; i++) {
        let item = text(targetText).findOne(1000);
        if (item) {
            item.click();
            toast("已点击:" + targetText);
            return true;
        }
        rv.scrollForward();
        sleep(500);
    }
    toast("未找到目标项");
    return false;
}

2.3 表单自动填写与批量输入

javascript 复制代码
// 自动填写表单
var inputs = className("android.widget.EditText").find();
inputs.forEach((input, i) => {
    input.setText("内容" + (i+1));
});

// 批量选择单选/多选框
className("android.widget.CheckBox").find().forEach(cb => {
    if (!cb.checked()) cb.click();
});

2.4 弹窗与对话框自动处理

javascript 复制代码
// 自动关闭常见弹窗
["关闭", "取消", "我知道了", "忽略"].forEach(txt => {
    let btn = text(txt).findOne(500);
    if (btn) btn.click();
});

// 检查并输入验证码弹窗
if (textMatches(/验证码/).exists()) {
    let input = className("android.widget.EditText").findOne();
    input.setText("123456");
    click("确定");
}

2.5 动态控件与属性适配

javascript 复制代码
// 动态 id/文本适配
var btn = id("btn_ok").exists() ? id("btn_ok").findOne() : textMatches(/(确定|OK|Yes)/).findOne();
btn && btn.click();

// 获取控件属性
var node = text("提交").findOne();
log("是否可见:" + node.visibleToUser());
log("是否可点击:" + node.clickable());
log("控件文本:" + node.text());

2.6 嵌套布局与复杂层级遍历

javascript 复制代码
// 遍历 FrameLayout 下所有 Button
var frame = className("android.widget.FrameLayout").findOne();
frame.children().forEach(child => {
    if (child.className() === "android.widget.Button") {
        log("按钮文本:" + child.text());
    }
});

// 递归查找所有 EditText
function findAllEditText(node, arr=[]) {
    if (!node) return arr;
    if (node.className() === "android.widget.EditText") arr.push(node);
    for (let i = 0; i < node.childCount(); i++) {
        findAllEditText(node.child(i), arr);
    }
    return arr;
}
var allInputs = findAllEditText(className("android.widget.LinearLayout").findOne());
log("共找到输入框:" + allInputs.length);

2.7 正则与模糊查找

javascript 复制代码
// 正则查找所有"领取"按钮并点击
textMatches(/(领取|Claim|Get)/).find().forEach(btn => btn.click());

// 模糊查找包含"红包"的控件
textContains("红包").find().forEach(node => log(node.text()));

2.8 UI 脚本与自动化结合

javascript 复制代码
"ui";
ui.layout(
    <vertical>
        <text textSize="22sp" textColor="#222">自动化表单填写</text>
        <input id="input1" hint="请输入A" />
        <input id="input2" hint="请输入B" />
        <button id="btn" text="自动填写" />
    </vertical>
);
ui.btn.on("click", () => {
    ui.input1.setText("自动A");
    ui.input2.setText("自动B");
    toast("已自动填写");
});

三、实战项目:自动化表单批量填写与提交

3.1 需求分析

  • 自动遍历页面所有表单输入框,批量填写内容
  • 自动选择所有多选框、单选框
  • 自动点击"提交"按钮
  • 支持动态表单、弹窗、验证码等复杂场景
  • 支持日志输出、异常处理、结果反馈

3.2 项目结构

plaintext 复制代码
autojs-formfill/
├── main.js
├── modules/
│   ├── formfill.js
│   └── logger.js
├── logs/
│   └── formfill.log
└── README.md

3.3 formfill.js 代码

javascript 复制代码
// modules/formfill.js
const logger = require("./logger.js");
function run(formData) {
    logger.log("开始自动填写表单");
    // 填写输入框
    var inputs = className("android.widget.EditText").find();
    inputs.forEach((input, i) => {
        input.setText(formData[i] || "内容" + (i+1));
    });
    // 选择所有多选框
    className("android.widget.CheckBox").find().forEach(cb => {
        if (!cb.checked()) cb.click();
    });
    // 选择所有单选框
    className("android.widget.RadioButton").find().forEach(rb => {
        if (!rb.checked()) rb.click();
    });
    // 自动点击"提交"按钮
    let btn = textMatches(/(提交|保存|确定)/).findOne(3000);
    if (btn) {
        btn.click();
        logger.log("已点击提交");
    } else {
        logger.log("未找到提交按钮");
    }
}
module.exports = { run };

3.4 日志模块 modules/logger.js

javascript 复制代码
// modules/logger.js
function log(msg) {
    let line = `[${new Date().toLocaleTimeString()}] ${msg}`;
    files.append("../logs/formfill.log", line + "\n");
    toast(msg);
}
module.exports = { log };

3.5 main.js 代码

javascript 复制代码
// main.js
const formfill = require("./modules/formfill.js");
const logger = require("./modules/logger.js");

// 示例表单数据
let formData = ["张三", "123456", "备注内容"];

// 启动自动化表单填写
formfill.run(formData);

// 日志输出
logger.log("表单自动化流程结束");

四、分步详解与进阶技巧

4.1 复杂层级控件的递归遍历

  • 递归查找所有输入框、按钮、列表项
  • 支持多层嵌套、动态生成控件

4.2 动态控件适配与容错

  • 动态 id/文本/属性适配,兼容不同版本
  • 正则、模糊查找提升适配率
  • 异常捕获,防止崩溃

4.3 列表懒加载与滚动加载

  • 自动滚动加载更多内容,批量操作
  • 支持分页、下拉刷新、上拉加载

4.4 弹窗与广告自动处理

  • 检查并自动关闭弹窗、广告、遮挡层
  • 支持多种弹窗类型、文本、控件适配

4.5 表单自动化与数据驱动

  • 支持从文件/网络读取表单数据,批量自动填写
  • 支持结果校验、异常重试、日志记录

4.6 UI 脚本与自动化协同

  • UI界面与自动化脚本联动,提升交互体验
  • 支持参数配置、结果展示、日志查看

4.7 多语言、多分辨率适配

  • 支持多语言控件文本、不同分辨率/品牌适配
  • 合理使用 dp/sp 单位,避免硬编码像素

4.8 高级控件操作性能优化

  • 控件查找加超时,避免死循环
  • 批量操作分批处理,减少卡顿
  • 日志分级输出,开发阶段多输出,正式运行时降级
  • 异步处理耗时操作,提升主流程响应
  • 定期清理无用变量、释放资源,降低内存占用

五、常见问题与解决方案

问题 解决方案
控件找不到/点击无效 检查控件属性、增加等待时间、尝试多种查找方式
列表项无法滚动/加载 检查列表类型、使用 scrollForward/scrollBackward
动态控件 id/文本变化 用正则、模糊查找、属性适配提升兼容性
弹窗/广告遮挡 增加弹窗检测与自动关闭逻辑
表单填写失败/内容丢失 检查输入框属性、输入方法、异常捕获
多语言/多分辨率适配问题 用 textMatches、textContains、dp/sp 单位适配
脚本卡顿/崩溃 优化控件查找、批量操作、加异常捕获
UI 脚本与自动化冲突 合理拆分主流程与 UI 逻辑,避免互相阻塞

六、性能优化建议

  • 控件查找建议加超时,避免死循环
  • 批量操作分批处理,减少卡顿
  • 动态控件适配,提升兼容性
  • 日志分级输出,开发阶段多输出,正式运行时降级
  • 异步处理耗时操作,提升主流程响应
  • 定期清理无用变量、释放资源,降低内存占用
  • 合理 sleep,避免无效等待
  • 多语言、多分辨率适配,提升用户体验
  • UI 脚本与自动化逻辑分离,提升健壮性

最后感谢阅读!欢迎关注我,微信公众号:《鲫小鱼不正经》。欢迎点赞、收藏、关注,一键三连!!!

相关推荐
盏茶作酒296 分钟前
打造自己的组件库(一)宏函数解析
前端·vue.js
山有木兮木有枝_25 分钟前
JavaScript 设计模式--单例模式
前端·javascript·代码规范
一大树40 分钟前
Vue3 开发必备:20 个实用技巧
前端·vue.js
颜渊呐1 小时前
uniapp中APPwebview与网页的双向通信
前端·uni-app
10年前端老司机1 小时前
React 受控组件和非受控组件区别和使用场景
前端·javascript·react.js
夏晚星1 小时前
vue实现微信聊天emoji表情
前端·javascript
停止重构1 小时前
【方案】前端UI布局的绝技,响应式布局,多端适配
前端·网页布局·响应式布局·grid布局·网页适配多端
極光未晚1 小时前
TypeScript在前端项目中的那些事儿:不止于类型的守护者
前端·javascript·typescript
ze_juejin1 小时前
Vue3 + Vite + Ant Design Vue + Axios + Pinia 脚手架搭建
前端·vue.js
lichenyang4531 小时前
React项目(移动app)
前端