E4X 界面语法 — 用 XML 声明式写界面
什么是 E4X
E4X(ECMAScript for XML)是 JavaScript 的 XML 扩展,让你可以用类似 HTML 的语法在脚本中声明式地构建 Android 原生界面。AutoJs6 内置的 ui 模块就是基于 E4X 实现的。
// E4X 示例 —— 一个简单的登录界面
"ui"; // 声明这是 UI 脚本
ui.layout(
<vertical padding="16">
<text text="AutoJs6 示例应用" textSize="20sp" textColor="#333"/>
<input id="username" hint="请输入用户名"/>
<input id="password" hint="请输入密码" password="true"/>
<button id="login" text="登录" w="*" h="auto"/>
</vertical>
);
ui.login.click(() => {
let name = ui.username.getText();
let pwd = ui.password.getText();
toast("登录: " + name);
});
基本结构
"ui" 声明
// 必须在脚本开头声明,告诉 AutoJs6 这是 UI 脚本
"ui";
ui.layout()
// 主界面布局 —— 在应用内全屏显示
ui.layout(
<vertical>
<text text="Hello"/>
</vertical>
);
// 悬浮窗布局 —— 作为浮动按钮显示
ui.floatyWindow(
<horizontal>
<button text="A"/>
<button text="B"/>
</horizontal>
);
布局容器
vertical — 垂直排列
ui.layout(
<vertical padding="16">
<text text="第一行"/>
<text text="第二行"/>
<text text="第三行"/>
</vertical>
);
horizontal — 水平排列
<horizontal>
<button text="左"/>
<button text="中"/>
<button text="右"/>
</horizontal>
frame — 帧布局(子控件叠加)
<frame w="*" h="300">
<img src="/sdcard/bg.png" w="*" h="*"/>
<text text="覆盖在图片上" layout_gravity="center"/>
</frame>
RelativeLayout — 相对布局
<RelativeLayout w="*" h="*">
<button id="btn1" text="按钮1" w="100" h="50"/>
<button id="btn2" text="按钮2"
layout_below="btn1"
layout_toRightOf="btn1"/>
</RelativeLayout>
常用属性
宽高
// w = width, h = height
<button w="auto" h="auto"/> // 自适应
<button w="*" h="auto"/> // 撑满父容器宽度
<button w="200" h="50"/> // 固定像素值
<button w="50dp" h="40dp"/> // dp 单位
<button w="50%" h="auto"/> // 百分比
padding 和 margin
<button padding="10">文字内边距</button>
<button margin="10">控件外边距</button>
<button paddingLeft="20" marginTop="10">分别设置</button>
文字属性
<text
text="显示的文字"
textSize="16sp" // 字号
textColor="#333333" // 颜色
textStyle="bold" // 加粗
gravity="center" // 居中
lines="2" // 最多 2 行
ellipsize="end" // 末尾省略
/>
背景
<button bg="#FF5722"/> // 纯色
<button bg="@drawable/bg_shape"/> // drawable 资源
<button bg="gradient"/> // 预设渐变
控件 id 与事件绑定
用 id 获取控件引用
ui.layout(
<vertical>
<button id="myBtn" text="点我"/>
<text id="result" text="等待点击..."/>
</vertical>
);
// 通过 ui.控件id 获取引用
ui.myBtn.click(() => {
ui.result.setText("按钮被点击了!");
});
事件类型
// 点击
ui.btn.click(() => {});
// 长按
ui.btn.longClick(() => {});
// 文本变化(输入框)
ui.input.on("change", (text) => {
console.log("输入: " + text);
});
// 焦点变化
ui.input.on("focus", (hasFocus) => {
console.log("焦点: " + hasFocus);
});
// 触摸事件
ui.btn.on("touch", (view, event) => {
let x = event.getRawX();
let y = event.getRawY();
});
常用控件
// 文本
<text text="内容"/>
// 按钮
<button text="按钮"/>
// 输入框
<input hint="提示文字" password="true"/>
// 图片
<img src="/sdcard/icon.png" w="50" h="50"/>
// 复选框
<checkbox text="同意条款" checked="false"/>
// 开关
<switch checked="true"/>
// 滑动条
<seekbar max="100" progress="50"/>
// 进度条
<progressbar max="100" progress="30"/>
// 滚动视图
<ScrollView h="*">
<vertical>
<text text="长文本..." textSize="14"/>
</vertical>
</ScrollView>
// 列表(需要自定义适配器,较复杂)
// 简单场景用 ScrollView + vertical 代替
动态更新界面
"ui";
ui.layout(
<vertical>
<text id="counter" text="0" textSize="40sp" gravity="center"/>
<button id="add" text="+1"/>
</vertical>
);
let count = 0;
ui.add.click(() => {
count++;
ui.counter.setText(count.toString());
});
实战:简易计算器
"ui";
ui.layout(
<vertical padding="20">
<text id="display" text="0" textSize="40sp" w="*" gravity="right"/>
<horizontal>
<button text="7" onclick="calc('7')"/>
<button text="8" onclick="calc('8')"/>
<button text="9" onclick="calc('9')"/>
<button text="/" onclick="calc('/')"/>
</horizontal>
<horizontal>
<button text="4" onclick="calc('4')"/>
<button text="5" onclick="calc('5')"/>
<button text="6" onclick="calc('6')"/>
<button text="*" onclick="calc('*')"/>
</horizontal>
<horizontal>
<button text="1" onclick="calc('1')"/>
<button text="2" onclick="calc('2')"/>
<button text="3" onclick="calc('3')"/>
<button text="-" onclick="calc('-')"/>
</horizontal>
<horizontal>
<button text="0" onclick="calc('0')"/>
<button text="." onclick="calc('.')"/>
<button text="=" onclick="calc('=')"/>
<button text="+" onclick="calc('+')"/>
</horizontal>
</vertical>
);
let expression = "";
function calc(input) {
if (input === "=") {
let result = eval(expression);
ui.display.setText(result.toString());
expression = result.toString();
} else {
expression += input;
ui.display.setText(expression);
}
}
调试技巧
实时预览
在 AutoJs6 中运行 UI 脚本时,界面会立即渲染显示。修改代码后重新运行即可看到更新。
查看控件属性
// 运行时检查控件状态
ui.layout(
<button id="test" text="按钮" enabled="true"/>
);
console.log("文字: " + ui.test.text());
console.log("启用: " + ui.test.isEnabled());
console.log("可见: " + ui.test.isVisible());
多界面切换
// 定义多个界面
let mainUI = () => ui.layout(
<vertical>
<button id="goNext" text="下一页"/>
</vertical>
);
let secondUI = () => ui.layout(
<vertical>
<text text="这是第二页"/>
</vertical>
);
mainUI();
ui.goNext.click(() => secondUI());