Autox.js E4X 界面编写 用 XML 和 JS 搭一个交互界面
脚本不止能"自动点",还能"自己有个界面"
Autox.js 不是只能跑后台脚本——你可以用它自带的界面系统给脚本搭一个真正的图形界面(有按钮、输入框、开关、列表),然后打包成 APK,给不会写代码的人当成一个普通 App 来用。
开启 UI 模式
脚本开头加一行 "ui";:
"ui";
ui.layout(
<vertical padding="16">
<text text="我的自动化工具" textSize="20sp" textColor="#333333"/>
<button id="startBtn" text="开始运行" marginTop="20"/>
<button id="stopBtn" text="停止"/>
</vertical>
);
// 按钮点击事件
ui.startBtn.click(() => {
toast("开始运行脚本");
});
ui.stopBtn.click(() => {
toast("停止");
});
保存、运行,你会看到一个真正的 Android Activity——有标题、有两个按钮、点了会弹窗。
E4X 是什么
E4X(ECMAScript for XML)是 ECMAScript 的一个扩展,允许你在 JS 代码里直接写 XML 字面量。Autox.js 把 E4X 作为它的 UI 描述语言——你写出的 XML 会被自动转换成 Android View 树。
布局容器
| 容器 | 对应 Android 布局 | 特点 |
|---|---|---|
<vertical> | LinearLayout(VERTICAL) | 从上到下排 |
<horizontal> | LinearLayout(HORIZONTAL) | 从左到右排 |
<frame> | FrameLayout | 叠放(后面的盖前面的) |
<relative> | RelativeLayout | 相对定位 |
<grid> | GridLayout | 网格排列 |
常用控件
ui.layout(
<vertical padding="16">
{/* 文本 */}
<text text="标题" textSize="24sp" textColor="#000000" gravity="center"/>
{/* 输入框 */}
<input id="nameInput" hint="请输入名字" inputType="text"/>
{/* 密码输入 */}
<input id="pwdInput" hint="密码" inputType="password"/>
{/* 按钮 */}
<button id="okBtn" text="确定"/>
{/* 开关 */}
<Switch id="autoRun" checked="true" text="自动运行"/>
{/* 进度条 */}
<ProgressBar id="progress" max="100"/>
{/* 图片 */}
<img src="file:///sdcard/icon.png" w="48" h="48"/>
{/* 列表 */}
<list id="myList" data="{{items}}">
<text text="{{this}}"/>
</list>
</vertical>
);
事件绑定
// 点击
ui.okBtn.click(() => {
let name = ui.nameInput.getText();
toast("你好," + name);
});
// 长按
ui.okBtn.longClick(() => {
toast("长按了");
return true; // 返回 true 表示消费了事件
});
// 值变化
ui.autoRun.on("checked", (checked) => {
console.log("开关变成了:" + checked);
});
// 输入变化
ui.nameInput.addTextChangedListener({
afterTextChanged: (s) => {
console.log("输入框值:" + s);
}
});
与脚本逻辑通信
UI 线程和脚本线程是分开的。脚本逻辑要操作 UI 时用 ui.run() 切到 UI 线程:
// 脚本线程里启动一个后台任务
threads.start(() => {
for (let i = 0; i <= 100; i++) {
sleep(50);
// 更新进度条要切到 UI 线程
ui.run(() => {
ui.progress.setProgress(i);
});
}
toast("完成!");
});
反过来,UI 线程要启动脚本逻辑时,用 threads.start() 把重活丢到后台线程,避免界面卡顿。
实战:自动签到工具界面
"ui";
ui.layout(
<vertical padding="20" bg="#F5F5F5">
<text text="每日自动签到" textSize="28sp" gravity="center" marginTop="40"/>
<view bg="#FFFFFF" w="*" marginTop="20" padding="16">
<text text="签到目标" textSize="14sp" textColor="#999"/>
<input id="target" w="*" hint="包名或 App 名" text="com.example.signin"/>
</view>
<view bg="#FFFFFF" w="*" marginTop="10" padding="16">
<text text="执行次数" textSize="14sp" textColor="#999"/>
<input id="count" w="*" inputType="number" text="1"/>
</view>
<Switch id="autoClose" checked="false" text="完成后自动关闭 App" marginTop="15"/>
<button id="runBtn" text="开始签到" w="*" h="auto" bg="#4CAF50" textColor="#FFFFFF" marginTop="30"/>
<text id="status" text="就绪" textSize="12sp" textColor="#666" gravity="center" marginTop="10"/>
</vertical>
);
ui.runBtn.click(() => {
ui.status.setText("正在运行...");
let target = ui.target.getText();
let count = parseInt(ui.count.getText()) || 1;
threads.start(() => {
try {
for (let i = 0; i < count; i++) {
ui.run(() => ui.status.setText("第 " + (i + 1) + "/" + count + " 次"));
runSignin(target);
sleep(1000);
}
ui.run(() => ui.status.setText("全部完成"));
} catch (e) {
ui.run(() => ui.status.setText("出错:" + e.message));
}
});
});
function runSignin(target) {
launchApp(target);
sleep(2000);
text("签到").findOne(5000)?.click();
sleep(1500);
home();
}
打包成独立 APK
带 UI 的脚本最适合打包成 APK——对用户来说就是"下载一个 App → 安装 → 点图标打开",完全看不到脚本代码。打包方法见脚本工程化分组。
局限性
- E4X 界面能力不如 React Native 或 Compose,布局和控件是 Android View 的子集
- 复杂交互(动画、手势、自定义绘制)比较困难
- 但对于"带几个输入框、几个按钮"的工具类应用,E4X 完全够用