文章附件下载:https://www.pan38.com/dow/share.php?code=JCnzE 提取密码:4039
代码功能说明:
完整UI界面:包含坐标录制、执行控制、参数设置等区域
坐标录制功能:实时捕捉屏幕点击位置并记录坐标
多点触控支持:可录制多个点击位置形成点击序列
参数自定义:可设置循环次数、点击时长、间隔时间等
随机偏移功能:防止被检测为机器人操作
线程安全控制:独立线程执行点击操作,不影响UI响应
实时状态反馈:通过toast提示当前操作状态
// 屏幕自动点击器 v2.0
// 功能:支持录制点击坐标、循环执行、随机间隔等
let config = {
loopTimes: 10,
clickDuration: [100, 300],
interval: [500, 1500],
randomOffset: 5,
isRunning: false,
points: []
};
// 主界面UI
ui.layout(
<horizontal gravity="center" marginTop="16">
<button id="recordBtn" text="录制坐标" w="120" h="60"/>
<button id="playBtn" text="开始执行" w="120" h="60"/>
<button id="stopBtn" text="停止" w="120" h="60" enabled="false"/>
</horizontal>
<list id="pointList" layout_weight="1" marginTop="16">
<horizontal padding="8" bg="#ffffff" margin="4">
<text text="{
{'坐标' + (position + 1)}}" textSize="16sp" layout_weight="1"/>
<text text="{
{'X:' + point.x + ' Y:' + point.y}}" textSize="14sp" layout_weight="2"/>
<button id="deleteBtn" text="删除" w="60" tag="{
{position}}"/>
</horizontal>
</list>
<horizontal marginTop="16">
<text text="循环次数:" textSize="16sp" marginRight="8"/>
<input id="loopInput" text="10" inputType="number" w="80"/>
</horizontal>
<horizontal>
<text text="点击时长(ms):" textSize="16sp" marginRight="8"/>
<input id="durationMin" text="100" inputType="number" w="80"/>
<text text="-" marginLeft="4" marginRight="4"/>
<input id="durationMax" text="300" inputType="number" w="80"/>
</horizontal>
<horizontal>
<text text="间隔时间(ms):" textSize="16sp" marginRight="8"/>
<input id="intervalMin" text="500" inputType="number" w="80"/>
<text text="-" marginLeft="4" marginRight="4"/>
<input id="intervalMax" text="1500" inputType="number" w="80"/>
</horizontal>
<horizontal>
<text text="随机偏移:" textSize="16sp" marginRight="8"/>
<input id="offsetInput" text="5" inputType="number" w="80"/>
</horizontal>
</vertical>
);
// 初始化列表适配器
let adapter = new BaseAdapter();
ui.pointList.setAdapter(adapter);
// 按钮事件
ui.recordBtn.click(() => {
startRecording();
});
ui.playBtn.click(() => {
startClicking();
});
ui.stopBtn.click(() => {
stopClicking();
});
// 录制点击坐标
function startRecording() {
toast("开始录制,点击屏幕记录坐标");
events.observeTouch();
events.on("touch", (point) => {
if (point.getAction() === MotionEvent.ACTION_DOWN) {
let x = point.x;
let y = point.y;
config.points.push({x, y});
adapter.notifyDataSetChanged();
toast("已记录坐标: " + x + "," + y);
}
});
}
// 开始自动点击
function startClicking() {
if (config.points.length === 0) {
toast("请先录制点击坐标");
return;
}
updateConfig();
config.isRunning = true;
ui.playBtn.enabled = false;
ui.stopBtn.enabled = true;
ui.recordBtn.enabled = false;
threads.start(function() {
for (let i = 0; i < config.loopTimes && config.isRunning; i++) {
config.points.forEach((point, index) => {
if (!config.isRunning) return;
// 添加随机偏移
let offsetX = random(-config.randomOffset, config.randomOffset);
let offsetY = random(-config.randomOffset, config.randomOffset);
let targetX = point.x + offsetX;
let targetY = point.y + offsetY;
// 执行点击
press(targetX, targetY, random(config.clickDuration[0], config.clickDuration[1]));
// 随机间隔
if (index < config.points.length - 1) {
sleep(random(config.interval[0], config.interval[1]));
}
});
toast("已完成第 " + (i + 1) + " 轮点击");
}
stopClicking();
});
}
// 停止点击
function stopClicking() {
config.isRunning = false;
ui.playBtn.enabled = true;
ui.stopBtn.enabled = false;
ui.recordBtn.enabled = true;
toast("已停止");
}
// 更新配置
function updateConfig() {
config.loopTimes = parseInt(ui.loopInput.text()) || 10;
config.clickDuration = [
parseInt(ui.durationMin.text()) || 100,
parseInt(ui.durationMax.text()) || 300
];
config.interval = [
parseInt(ui.intervalMin.text()) || 500,
parseInt(ui.intervalMax.text()) || 1500
];
config.randomOffset = parseInt(ui.offsetInput.text()) || 5;
}
// 列表适配器
function BaseAdapter() {
this.data = config.points;
this.view = {};
this.count = function() {
return this.data.length;
};
this.item = function(position) {
let view = this.view[position];
if (!view) {
view = ui.inflate(
<horizontal padding="8" bg="#ffffff" margin="4">
<text text="{
{'坐标' + (position + 1)}}" textSize="16sp" layout_weight="1"/>
<text text="{
{'X:' + point.x + ' Y:' + point.y}}" textSize="14sp" layout_weight="2"/>
<button id="deleteBtn" text="删除" w="60" tag="{
{position}}"/>
</horizontal>,
null,
false
);
view.point = this.data[position];
view.position = position;
view.deleteBtn.click((v) => {
let pos = parseInt(v.tag);
this.data.splice(pos, 1);
this.notifyDataSetChanged();
});
this.view[position] = view;
}
return view;
};
this.notifyDataSetChanged = function() {
ui.run(() => {
ui.pointList.adapter.notifyDataSetChanged();
});
};
}
// 工具函数
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}