
1. 从“坐标点击”到“控件操作”的认知跃迁很多刚接触Auto.js的朋友第一反应往往是“这不就是个模拟点击的脚本工具吗我直接找坐标点一下不就行了” 这个想法很自然也是很多自动化脚本的起点。我刚开始接触时也沉迷于用click(x, y)在各种App界面上戳来戳去感觉无所不能。但很快现实就给了我当头一棒换一台分辨率不同的手机脚本点击的位置就完全错位App界面稍微改版按钮挪了个地方脚本就彻底失效。这种基于绝对坐标的脚本脆弱得就像用沙子堆砌的城堡经不起任何风吹草动。这就是为什么我们需要从“坐标篇”这个看似基础实则关键的起点开始。坐标操作是Auto.js最底层的物理交互方式它直接模拟了手指触摸屏幕的行为。理解它不仅是学会一个click()函数更是理解后续所有“基于控件”的高级操作如click(‘确定’)、findOne(‘按钮’)的基石和兜底方案。当控件识别失效、当界面元素无法被准确捕获时坐标操作就是我们最后的、也是最可靠的武器。本篇笔记我将带你系统性地掌握坐标操作的核心原理、精准获取坐标的方法论、以及如何编写出更健壮的坐标脚本让你在自动化之路上走得更稳、更远。2. 坐标系统的核心原理屏幕背后的数字网格要玩转坐标首先得明白Auto.js或者说Android系统如何看待你的手机屏幕。你可以把你的手机屏幕想象成一张巨大的、透明的方格纸。2.1 坐标系原点与方向这张方格纸的原点 (0, 0)固定在屏幕的左上角。这是一个非常重要的约定与我们在数学中常见的右下角为原点的坐标系不同。X轴水平方向从左向右递增。屏幕最左边的X坐标为0最右边的X坐标等于屏幕宽度减1例如在1080x2340分辨率的屏幕上X轴范围是0到1079。Y轴垂直方向从上向下递增。屏幕最上边的Y坐标为0最下边的Y坐标等于屏幕高度减1同上例Y轴范围是0到2339。所以屏幕右下角的坐标就是(width-1, height-1)。任何一点的位置都可以用一个(x, y)的二元组唯一确定。2.2 分辨率与坐标的绝对性这里就引出了坐标操作最大的挑战绝对性。click(500, 1000)这个命令在任何设备上都会尝试去点击屏幕上的(500, 1000)这个绝对位置。如果两台手机分辨率不同这个点代表的实际物理位置比如是“微信”图标还是空白处就天差地别。因此在编写基于坐标的脚本时你必须时刻清楚当前脚本是针对何种分辨率的设备编写的。一个常见的良好实践是在脚本开头用device.width和device.height获取当前设备的屏幕宽高并判断是否符合你的预期。// 脚本启动时检查屏幕分辨率 let screenWidth device.width; let screenHeight device.height; console.log(当前屏幕分辨率: ${screenWidth}x${screenHeight}); // 假设你的脚本是为1080x2340设计的 if (screenWidth ! 1080 || screenHeight ! 2340) { toast(“警告脚本分辨率与当前设备不匹配可能点击不准”); // 这里可以加入动态适配的逻辑后文会讲 }3. 精准获取坐标的四大实战方法知道了原理接下来就是如何找到我们想点击的那个按钮的准确坐标。以下是四种我从实战中总结出的方法各有优劣。3.1 方法一使用Auto.js内置的“悬浮窗”与“布局分析”这是最常用、最直观的方法尤其适合初学者。确保Auto.js的“无障碍服务”和“悬浮窗权限”已开启。在Auto.js的侧边栏或脚本执行界面找到“布局范围分析”或类似名称不同版本可能叫“布局分析”、“界面分析”功能并开启。屏幕上会出现一个半透明的红色图层上面布满了网格和坐标显示。将手指或鼠标移动到你想点击的位置悬浮窗上会实时显示当前的(x, y)坐标。记下这个坐标。为了精确我通常会在目标按钮的中心区域轻微移动确认一个稳定的坐标值。注意有些设备的“开发者选项”中有一个“指针位置”功能也能显示触摸坐标但Auto.js的悬浮窗是与其脚本环境结合最紧密的工具推荐优先使用。3.2 方法二通过“控件”信息反推坐标进阶当你已经对控件操作有初步了解或者目标是一个标准的按钮/文本控件时可以先用控件探测工具如findOne()找到它然后获取其控件对象的bounds()属性。这个属性返回一个Rect对象包含了控件左上角(left, top)和右下角(right, bottom)的坐标。// 假设我们找到了一个“确定”按钮 let okButton className(“Button”).text(“确定”).findOne(); if (okButton) { let bounds okButton.bounds(); let centerX bounds.centerX(); // 中心点X坐标 let centerY bounds.centerY(); // 中心点Y坐标 console.log(按钮中心坐标: (${centerX}, ${centerY})); console.log(按钮范围: [${bounds.left}, ${bounds.top}]-[${bounds.right}, ${bounds.bottom}]); // 我们可以选择点击中心点 click(centerX, centerY); }这种方法获取的坐标非常精准且与控件绑定。但前提是控件必须能被正确识别。3.3 方法三截图电脑端取点高精度对于需要极高精度或者悬浮窗使用不便的场景比如某些游戏界面会屏蔽悬浮窗可以采用“截图-传电脑-取坐标”的方式。在目标界面使用captureScreen(“/sdcard/target.png”)命令截图。将截图文件传输到电脑上。在电脑上用任何一款有坐标显示功能的图片查看器或编辑软件如Windows自带的“画图”软件左下角会显示鼠标坐标或者更专业的Photoshop、GIMP等。在电脑软件中将鼠标移动到按钮中心记录下显示的像素坐标(x_pc, y_pc)。这个坐标就是你在手机屏幕上需要点击的坐标。实操心得确保截图时和点击时界面状态完全一致没有动态元素变化。并且电脑上查看的图片必须是原始尺寸不要缩放否则坐标会对不上。3.4 方法四基于比例的动态坐标计算多设备适配这是让坐标脚本具备一定“弹性”和“适应性”的关键技术。其核心思想是不记录绝对坐标而是记录目标点相对于屏幕宽高的比例。例如你发现在你的1080x2340测试机上“微信”图标位于(150, 2000)。那么它的相对位置是ratioX 150 / 1080 ≈ 0.1389ratioY 2000 / 2340 ≈ 0.8547在脚本中你可以这样写function clickByRatio(targetRatioX, targetRatioY) { let x Math.floor(device.width * targetRatioX); let y Math.floor(device.height * targetRatioY); console.log(计算得到坐标: (${x}, ${y})); click(x, y); } // 使用之前计算好的比例点击“微信” clickByRatio(0.1389, 0.8547);这样无论脚本运行在720p还是1440p的设备上它都会尝试去点击屏幕相对位置相同的点大大提升了脚本的跨设备兼容性。当然这种方法要求不同设备上App的图标布局是按屏幕比例缩放的这对于很多系统桌面和主流App的底部标签栏是成立的但对于复杂或不规则的界面则可能失效。4. 核心坐标操作函数详解与避坑指南Auto.js提供了几个核心函数来执行坐标操作看似简单但细节决定成败。4.1click(x, y)基础点击但不止于点击click(x, y)是最常用的函数它模拟了一次在(x, y)点的瞬时点击即按下后立即抬起。click(500, 1000); // 点击坐标(500, 1000)避坑点1点击无响应。有些控件尤其是游戏或自定义控件需要一定的按压时间才能触发。单纯的瞬时点击可能无效。此时需要用到press(x, y, duration)。避坑点2坐标越界。永远不要假设你的坐标在屏幕范围内。一个健壮的脚本应该加入检查function safeClick(x, y) { if (x 0 x device.width y 0 y device.height) { click(x, y); } else { console.error(坐标(${x}, ${y})超出屏幕范围); } }4.2press(x, y, duration)长按与精确控制press(x, y, duration)用于模拟长按操作。duration参数是按压的毫秒数。press(500, 1000, 1500); // 在(500, 1000)位置长按1.5秒这个函数极其有用触发长按菜单如文件长按删除、应用图标长按出菜单。解决点击无效对于反应“迟钝”的控件尝试将duration设置为100-300毫秒模拟一个稍长的点击往往能解决问题。拖动操作的前置很多拖动操作需要先长按选中目标。4.3swipe(x1, y1, x2, y2, duration)与gesture()滑动与手势滑动是除了点击外第二高频的操作。swipe从点(x1, y1)滑动到点(x2, y2)整个过程持续duration毫秒。// 从屏幕中部向上滑动类似翻页 swipe(device.width / 2, device.height * 2/3, device.width / 2, device.height / 3, 500);duration控制滑动的速度。时间越短滑动越快、越像“快速翻页”时间越长滑动越慢、越像“缓慢拖动”。需要根据实际效果调整。gesture用于模拟更复杂的手势如多点触控、自定义路径。它接受一个时间数组和一系列坐标点可以精确控制触点的移动轨迹。对于简单的直线滑动swipe更直观对于复杂的解锁图案或绘图gesture是唯一选择。// 模拟一个简单的Z字形滑动例如某些游戏的特定操作 gesture(1000, [0], [ // 1000ms内完成单指[0] [100, 500], // 起点 [300, 500], // 向右移动 [300, 800], // 向下移动 [500, 800] // 再次向右移动形成Z字 ]);4.4 坐标操作的“人性化”修饰随机与容差机器操作之所以容易被检测就是因为太“完美”、太“规律”。人类的点击会有微小偏差滑动速度会有变化。为了让脚本更“像人”我们必须引入随机性。1. 点击坐标随机偏移不要每次都点击绝对相同的像素点。可以在目标坐标周围一个小范围内随机偏移。function humanClick(x, y, radius) { // radius 为随机偏移的最大半径例如5-10像素 let offsetX random(-radius, radius); let offsetY random(-radius, radius); click(x offsetX, y offsetY); }2. 滑动时间与路径随机化function humanSwipe(x1, y1, x2, y2, baseDuration) { let duration baseDuration random(-200, 200); // 基础时间±200ms随机 // 甚至可以引入路径中间点的微小扰动 swipe(x1, y1, x2, y2, duration); }3. 操作间隔随机化在连续操作之间加入随机的延迟模仿人类的反应时间。sleep(random(800, 1500)); // 等待0.8到1.5秒之间的一个随机时间这些“人性化”处理能极大降低脚本被简单规则检测到的风险是编写高质量自动化脚本的必备技巧。5. 实战案例编写一个健壮的“自动清理后台”脚本让我们综合运用以上所有知识编写一个实用脚本自动清理手机后台任务。这个操作通常涉及点击“多任务键”或上滑悬停、然后点击“清除全部”按钮。由于多任务界面控件识别可能因系统而异我们用坐标实现。5.1 第一步分析操作流程与获取关键坐标激活多任务界面对于全面屏手势通常是从屏幕底部向上滑动并停顿。这是一个swipe操作终点需要停顿所以用press模拟长按滑动起点可能更可靠但这里我们用gesture更精确。定位“清除全部”按钮在多任务界面这个按钮通常位于屏幕底部中央或右下角。我们需要用3.1或3.3的方法在自己的手机上确定其坐标。假设我们测得为(clearX, clearY)。点击“清除全部”一个简单的click。返回桌面按一次“Home”键通常可用back()函数但有些系统多任务界面按back会返回上一个App所以这里用模拟Home键home()。5.2 第二步编写具有容错和适配能力的脚本// 自动清理后台任务脚本 (坐标版) // 作者根据个人设备调试请注意适配 console.show(); // 显示控制台方便调试 // 第一部分设备检查与坐标定义 (需根据自己设备修改!) let screenWidth device.width; let screenHeight device.height; console.log(当前设备: ${screenWidth}x${screenHeight}); // 定义关键坐标这里以1080x2340为例并转换为比例方便适配 // 1. 上滑打开多任务手势的起点、终点底部中央上滑 let swipeStartRatio {x: 0.5, y: 0.9}; // 屏幕底部中央 let swipeEndRatio {x: 0.5, y: 0.4}; // 滑动到屏幕中部偏上 // 计算实际坐标 let swipeStartX Math.floor(screenWidth * swipeStartRatio.x); let swipeStartY Math.floor(screenHeight * swipeStartRatio.y); let swipeEndX Math.floor(screenWidth * swipeEndRatio.x); let swipeEndY Math.floor(screenHeight * swipeEndRatio.y); // 2. “清除全部”按钮的坐标比例请用悬浮窗在自己的多任务界面确认 // 例如在小米手机上可能位于底部中央 let clearBtnRatio {x: 0.5, y: 0.85}; let clearBtnX Math.floor(screenWidth * clearBtnRatio.x); let clearBtnY Math.floor(screenHeight * clearBtnRatio.y); // 第二部分人性化操作函数 function humanSwipe(x1, y1, x2, y2) { let duration 800 random(0, 400); // 800-1200ms随机时长 console.log(模拟上滑: [${x1},${y1}] - [${x2},${y2}], 时长${duration}ms); swipe(x1, y1, x2, y2, duration); } function humanClick(x, y, desc) { let offset random(-8, 8); // ±8像素内随机偏移 let targetX x offset; let targetY y offset; // 安全边界检查 targetX Math.max(0, Math.min(screenWidth - 1, targetX)); targetY Math.max(0, Math.min(screenHeight - 1, targetY)); console.log(${desc}: 点击坐标 (${targetX}, ${targetY})); click(targetX, targetY); sleep(random(300, 700)); // 点击后随机等待 } // 第三部分主流程 console.log(“开始执行后台清理流程...”); // 步骤1上滑打开多任务界面模拟手势 humanSwipe(swipeStartX, swipeStartY, swipeEndX, swipeEndY); sleep(1000 random(0, 500)); // 等待界面完全弹出 // 步骤2点击“清除全部”按钮 humanClick(clearBtnX, clearBtnY, “点击清除全部”); sleep(800 random(0, 400)); // 等待清理动画完成 // 步骤3返回桌面按Home键 console.log(“返回桌面”); home(); sleep(500); console.log(“后台清理完成”); toast(“后台已清理”);5.3 第三步调试与优化建议首次运行必调第一次运行脚本很大概率会失败因为swipeEndRatio和clearBtnRatio需要你根据自己手机的实际效果进行微调。打开控制台观察日志如果滑动不到位就增大swipeEndRatio.y的值比如从0.4调到0.5如果点不到清除按钮就调整clearBtnRatio。增加视觉确认可选进阶为了让脚本更可靠可以在点击“清除全部”前加入一个简单的颜色判断。例如先截图判断目标坐标(clearBtnX, clearBtnY)的颜色是否是你预期的按钮颜色比如一个红色的叉。这需要用到images模块的captureScreen()和getPixel()函数复杂度会增加但鲁棒性会极大提升。异常处理脚本没有加入try...catch在实际复杂环境中可以考虑包裹可能失败的操作并提供重试机制。6. 坐标操作的局限性及何时应转向控件操作尽管我们花了很大篇幅学习坐标操作但必须清醒认识到它的天花板。坐标操作的“硬伤”设备依赖性强跨分辨率、跨比例如16:9, 19.5:9, 20:9设备适配麻烦即使使用比例法也无法应对UI布局彻底改变的情况。动态界面无力对于内容会滚动、会变化的列表按钮的绝对坐标或相对比例都在不断变化。缺乏语义click(500, 1000)完全不知道点击的是什么脚本的逻辑可读性和可维护性差。何时应该使用控件操作当界面元素可以通过id、text、className、desc等属性稳定地识别时毫不犹豫地选择控件操作。例如click(“确定”)比click(900, 1800)直观一万倍。findOne(text(“微信”)).click()无论在屏幕哪个位置都能找到并点击。控件操作能获取元素状态是否可点击、是否被选中能处理列表循环findEach()这些都是坐标操作无法比拟的。坐标操作的“正确定位”兜底方案当所有控件识别方法都失效时如游戏界面、某些定制化App的Canvas绘制元素坐标是最后的武器。固定场景对于系统级、UI几乎不变的固定操作如从固定位置下滑状态栏、点击固定的导航栏按钮坐标法简单直接。手势模拟复杂的滑动、绘制手势本质上还是坐标序列的操作。所以我的学习建议是扎实掌握坐标操作理解其底层逻辑和局限性然后尽快迈向更高级、更稳定的控件操作学习。将两者结合使用才能应对真实的、复杂的自动化场景。例如先用坐标操作滑动到目标区域再用控件识别定位并操作其中的具体元素。这才是Auto.js高手之路。