|
|
自定义悬浮操作球可拖动小球点按展开
- // =============================================================
- // 案例 ⑤ 悬浮操作球(可拖动小球 + 点按展开)+ 循环任务
- // -------------------------------------------------------------
- // 这是 floatUI 的「另一种」写法,专门和 H5HTML 那个「可拖动大控制台
- // (开始/暂停/恢复/停止 + 状态 + 日志)」区分开,二者互为补充:
- // · H5HTML 控制台 = 固定大面板、多按钮、带日志/心跳;
- // · 本例 ⑤ = 一个小球,拖动移位、点一下展开成快捷操作、再点收起。
- //
- // 本例演示的要点:
- // ① 隐藏 AIWROK 系统自带浮标(圆形 A 球):new floatUI().hideSystemFloat()
- // —— 这是 floatUI 的实例方法(用户用官方 API 纠正:别用不存在的 closeAll)。
- // 配套还有 showSystemFloat() / setSystemPosition(x,y)。
- // ② 小球拖动:importClass View/MotionEvent + OnTouchListener + getRawX/Y;
- // 同一个小球上「按下→移动超阈值=拖动,几乎没动=点按」自动区分。
- // ③ 展开/收起:View.VISIBLE / View.GONE 切换面板。
- // ④ 循环任务放后台线程,进度用 runOnUiThread 回主线程刷小球文字。
- // ⑤ 关闭本脚本自己的浮窗:跟踪实例 + ui.close()(floatUI 没有 closeAll)。
- // 用法:运行 → 屏幕出现可拖动小球 → 点小球展开 → 点「自动刷」循环上滑 → 「收工」关窗。
- // 铁律:floatUI 根/控件只认原生 Android 类名(LinearLayout/FrameLayout/TextView/Button…)。
- // =============================================================
- // ① 隐藏系统自带浮标(floatUI 实例方法,启动即生效)
- try { new floatUI().hideSystemFloat(); } catch (e) {}
- try { importClass(android.view.View); } catch (e) {}
- try { importClass(android.view.MotionEvent); } catch (e) {}
- function resolveView() {
- if (typeof View !== 'undefined' && View) return View;
- try { if (android && android.view && android.view.View) return android.view.View; } catch (e) {}
- return null;
- }
- function resolveMotionEvent() {
- if (typeof MotionEvent !== 'undefined' && MotionEvent) return MotionEvent;
- try { if (android && android.view && android.view.MotionEvent) return android.view.MotionEvent; } catch (e) {}
- return null;
- }
- function rnd(a, b) { return a + Math.floor(Math.random() * (b - a + 1)); }
- function sw() { try { return screen.getScreenWidth(); } catch (e) { return 1080; } }
- function sh() { try { return screen.getScreenHeight(); } catch (e) { return 1920; } }
- function sleepMs(ms) { try { sleep.millisecond(ms); } catch (e) { try { java.lang.Thread.sleep(ms); } catch (e2) {} } }
- // 人类化上滑(复用案例③思路):起点终点各 ±8 抖动,更像真人
- function humanSwipeUp() {
- var x = Math.round(sw() * 0.5);
- var y1 = rnd(Math.round(sh() * 0.78), Math.round(sh() * 0.82));
- var y2 = rnd(Math.round(sh() * 0.18), Math.round(sh() * 0.22));
- var d = rnd(420, 680);
- try { auto.swip(x, y1, x, y2, d, 0); }
- catch (e) { try { auto.swipe(x, y1, x, y2, d); } catch (e2) { printl("[ERR] 滑动失败: " + e2); } }
- }
- // ---------- 状态 ----------
- var ui = null, ctrls = {};
- var winX = 60, winY = 180; // 小球初始位置
- var dragging = false, dragLastX = 0, dragLastY = 0, downX = 0, downY = 0;
- var running = false, round = 0;
- var ROUNDS = 15; // 自动刷轮数(到点自动收工)
- var worker = null;
- var hbOn = true; // 保活心跳开关:关窗时置 false,脚本自然结束
- var G_FLOATS = []; // 本脚本创建的 floatUI 实例(用于启动时清残留)
- // ---------- 布局:可拖动小球 + 可展开面板(竖向 LinearLayout,面板默认隐藏) ----------
- function buildXml() {
- return '' +
- '<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ' +
- ' android:layout_width="wrap_content" android:layout_height="wrap_content" ' +
- ' android:orientation="vertical" android:padding="0dp" ' +
- ' android:background="#E61A2B3C">' +
- // 小球(拖动把手 + 点按展开/收起)
- ' <Button android:id="ball" android:layout_width="56dp" android:layout_height="56dp" ' +
- ' android:text="AI" android:textColor="#FFFFFF" android:textSize="16sp" ' +
- ' android:background="#16A34A" android:gravity="center"/>' +
- // 展开面板(默认 GONE)
- ' <LinearLayout android:id="panel" android:layout_width="200dp" android:layout_height="wrap_content" ' +
- ' android:orientation="vertical" android:background="#E61A2B3C" android:padding="10dp" ' +
- ' android:visibility="gone">' +
- ' <TextView android:id="tip" android:layout_width="match_parent" android:layout_height="wrap_content" ' +
- ' android:text="点「自动刷」开始,循环上滑" android:textColor="#86EFAC" android:textSize="12sp" android:paddingBottom="8dp"/>' +
- ' <Button android:id="btnRun" android:layout_width="match_parent" android:layout_height="38dp" ' +
- ' android:text="▶ 自动刷" android:textColor="#FFFFFF" android:textSize="13sp" android:background="#2563EB" android:layout_marginBottom="6dp"/>' +
- ' <Button android:id="btnStop" android:layout_width="match_parent" android:layout_height="38dp" ' +
- ' android:text="⏹ 收工" android:textColor="#FFFFFF" android:textSize="13sp" android:background="#B91C1C"/>' +
- ' </LinearLayout>' +
- '</LinearLayout>';
- }
- function moveTo(x, y) {
- var screenW = sw(), screenH = sh();
- if (x < 0) x = 0; if (y < 0) y = 0;
- if (x > screenW - 60) x = screenW - 60;
- if (y > screenH - 60) y = screenH - 60;
- winX = x; winY = y;
- try { ui.setPosition(x, y); } catch (e) {}
- }
- // 展开 / 收起面板
- function togglePanel() {
- var V = resolveView();
- try {
- if (V && V.GONE !== undefined && ctrls.panel && ctrls.panel.setVisibility) {
- var vis = ctrls.panel.getVisibility();
- ctrls.panel.setVisibility(vis === V.VISIBLE ? V.GONE : V.VISIBLE);
- printl(vis === V.VISIBLE ? '🔼 面板已收起' : '🔽 面板已展开');
- }
- } catch (e) { printl('⚠ 展开/收起失败: ' + e); }
- }
- // 后台循环刷(子线程里跑,不直接碰 UI)
- function loopSwipe() {
- while (running && round < ROUNDS) {
- round++;
- humanSwipeUp();
- sleepMs(rnd(900, 1400));
- // 回主线程刷小球 / 提示文字
- try {
- var t = new thread();
- t.runOnUiThread(function () {
- try { if (ctrls.ball) ctrls.ball.setText(round + '/' + ROUNDS); } catch (e) {}
- try { if (ctrls.tip) ctrls.tip.setText('刷到第 ' + round + ' 次'); } catch (e) {}
- });
- } catch (e) {}
- }
- // 收尾:回主线程提示,3 秒后自动关窗并结束脚本
- try {
- var t2 = new thread();
- t2.runOnUiThread(function () {
- try { if (ctrls.ball) ctrls.ball.setText('✔'); } catch (e) {}
- try { if (ctrls.tip) ctrls.tip.setText('已完成 ' + ROUNDS + ' 次,准备收工'); } catch (e) {}
- setRunEnabled(true); // 完成后恢复按钮(3 秒内可再次点击)
- printl('🏁 自动刷完成,3 秒后关窗');
- try { runTime.setTimeout(function () { try { ui.close(); } catch (e) {} hbOn = false; }, 3000); } catch (e) {}
- });
- } catch (e) {}
- running = false;
- }
- // 切换「自动刷」按钮的启用/禁用与外观(运行时禁用并变灰,避免重复点击 / 给出明确反馈)
- function setRunEnabled(on) {
- try {
- if (!ctrls.btnRun) return;
- ctrls.btnRun.setEnabled(on);
- ctrls.btnRun.setClickable(on);
- ctrls.btnRun.setText(on ? '▶ 自动刷' : '● 运行中');
- try { ctrls.btnRun.setBackgroundColor(on ? 0xFF2563EB : 0xFF555555); } catch (e2) {}
- } catch (e) {}
- }
- function cmdRun() {
- if (running) return;
- running = true; round = 0;
- setRunEnabled(false); // 运行时禁用按钮 + 显示"运行中"
- printl('▶ 自动刷开始(共 ' + ROUNDS + ' 次上滑)');
- worker = new thread();
- worker.runJsCode(function () { loopSwipe(); }, '自动刷线程');
- }
- function cmdStop() {
- running = false; hbOn = false;
- setRunEnabled(true); // 收工后恢复按钮(窗口随即关闭,留底防重开)
- printl('⏹ 收工,关闭窗口');
- try { if (worker && worker.isAlive()) worker.stop(); } catch (e) {}
- try { ui.close(); } catch (e) {}
- }
- // 拖动 + 点按 二合一(绑在小球上:移动超阈值=拖动,几乎没动=点按展开)
- function setupDrag() {
- var V = resolveView(), M = resolveMotionEvent();
- if (!V || !M || !ctrls.ball || !ctrls.ball.setOnTouchListener) {
- printl('⚠ 拖拽不可用(缺 View/MotionEvent),小球用初始位置(仍可点按展开)');
- return;
- }
- try {
- ctrls.ball.setOnTouchListener(new V.OnTouchListener({
- onTouch: function (view, event) {
- try {
- switch (event.getAction()) {
- case M.ACTION_DOWN:
- dragging = false;
- downX = event.getRawX(); downY = event.getRawY();
- dragLastX = downX; dragLastY = downY;
- return true;
- case M.ACTION_MOVE: {
- var mx = event.getRawX(), my = event.getRawY();
- if (!dragging && (Math.abs(mx - downX) > 8 || Math.abs(my - downY) > 8)) dragging = true;
- if (dragging) {
- moveTo(winX + (mx - dragLastX), winY + (my - dragLastY));
- dragLastX = mx; dragLastY = my;
- }
- return true;
- }
- case M.ACTION_UP:
- if (!dragging) togglePanel(); // 视为点按 → 展开/收起
- dragging = false;
- return true;
- }
- } catch (e2) { return false; }
- return false;
- }
- }));
- printl('✔ 小球可拖动、可点按展开');
- } catch (e) { printl('⚠ 拖拽绑定失败: ' + e); }
- }
- // 保活心跳:主线程一空闲脚本就结束、窗口会被回收,故用定时器递归保活;
- // running 时持续保活,收工/完成后置 hbOn=false 自然结束。
- function heartbeat() {
- if (!hbOn) return;
- runTime.setTimeout(heartbeat, 1000);
- }
- function main() {
- printl('===== ⑤ 悬浮操作球(可展开)+ 循环任务 =====');
- // 启动前清掉上次残留的浮窗(跟踪本脚本创建的实例,逐个 ui.close())
- for (var i = 0; i < G_FLOATS.length; i++) { try { G_FLOATS[i].close(); } catch (e) {} }
- G_FLOATS = [];
- ui = new floatUI(); G_FLOATS.push(ui);
- ui.loadXML(buildXml());
- ctrls.ball = ui.findViewById('ball');
- ctrls.panel = ui.findViewById('panel');
- ctrls.tip = ui.findViewById('tip');
- ctrls.btnRun = ui.findViewById('btnRun');
- ctrls.btnStop = ui.findViewById('btnStop');
- if (!ctrls.ball) { printl('✘ 小球控件未取到,设备可能不支持 floatUI'); return; }
- setupDrag();
- try { ctrls.btnRun.setOnClickListener(function () { try { cmdRun(); } catch (e) {} }); } catch (e) {}
- try { ctrls.btnStop.setOnClickListener(function () { try { cmdStop(); } catch (e) {} }); } catch (e) {}
- moveTo(winX, winY);
- heartbeat(); // 启动保活
- printl('小球已出现:拖动移位;点小球展开面板;点「自动刷」循环上滑;「收工」关窗');
- }
- main();
复制代码
|
|