B2B网络软件

标题: 自定义悬浮操作球可拖动小球点按展开 [打印本页]

作者: YYPOST群发软件    时间: 1 小时前
标题: 自定义悬浮操作球可拖动小球点按展开


自定义悬浮操作球可拖动小球点按展开
自定义悬浮操作球可拖动小球点按展开 B2B网络软件

自定义悬浮操作球可拖动小球点按展开 B2B网络软件

自定义悬浮操作球可拖动小球点按展开 B2B网络软件



  1. // =============================================================
  2. // 案例 ⑤  悬浮操作球(可拖动小球 + 点按展开)+ 循环任务
  3. // -------------------------------------------------------------
  4. // 这是 floatUI 的「另一种」写法,专门和 H5HTML 那个「可拖动大控制台
  5. // (开始/暂停/恢复/停止 + 状态 + 日志)」区分开,二者互为补充:
  6. //   · H5HTML 控制台 = 固定大面板、多按钮、带日志/心跳;
  7. //   · 本例 ⑤      = 一个小球,拖动移位、点一下展开成快捷操作、再点收起。
  8. //
  9. // 本例演示的要点:
  10. //   ① 隐藏 AIWROK 系统自带浮标(圆形 A 球):new floatUI().hideSystemFloat()
  11. //      —— 这是 floatUI 的实例方法(用户用官方 API 纠正:别用不存在的 closeAll)。
  12. //      配套还有 showSystemFloat() / setSystemPosition(x,y)。
  13. //   ② 小球拖动:importClass View/MotionEvent + OnTouchListener + getRawX/Y;
  14. //      同一个小球上「按下→移动超阈值=拖动,几乎没动=点按」自动区分。
  15. //   ③ 展开/收起:View.VISIBLE / View.GONE 切换面板。
  16. //   ④ 循环任务放后台线程,进度用 runOnUiThread 回主线程刷小球文字。
  17. //   ⑤ 关闭本脚本自己的浮窗:跟踪实例 + ui.close()(floatUI 没有 closeAll)。
  18. // 用法:运行 → 屏幕出现可拖动小球 → 点小球展开 → 点「自动刷」循环上滑 → 「收工」关窗。
  19. // 铁律:floatUI 根/控件只认原生 Android 类名(LinearLayout/FrameLayout/TextView/Button…)。
  20. // =============================================================

  21. // ① 隐藏系统自带浮标(floatUI 实例方法,启动即生效)
  22. try { new floatUI().hideSystemFloat(); } catch (e) {}

  23. try { importClass(android.view.View); } catch (e) {}
  24. try { importClass(android.view.MotionEvent); } catch (e) {}

  25. function resolveView() {
  26.     if (typeof View !== 'undefined' && View) return View;
  27.     try { if (android && android.view && android.view.View) return android.view.View; } catch (e) {}
  28.     return null;
  29. }
  30. function resolveMotionEvent() {
  31.     if (typeof MotionEvent !== 'undefined' && MotionEvent) return MotionEvent;
  32.     try { if (android && android.view && android.view.MotionEvent) return android.view.MotionEvent; } catch (e) {}
  33.     return null;
  34. }
  35. function rnd(a, b) { return a + Math.floor(Math.random() * (b - a + 1)); }
  36. function sw() { try { return screen.getScreenWidth(); } catch (e) { return 1080; } }
  37. function sh() { try { return screen.getScreenHeight(); } catch (e) { return 1920; } }
  38. function sleepMs(ms) { try { sleep.millisecond(ms); } catch (e) { try { java.lang.Thread.sleep(ms); } catch (e2) {} } }

  39. // 人类化上滑(复用案例③思路):起点终点各 ±8 抖动,更像真人
  40. function humanSwipeUp() {
  41.     var x = Math.round(sw() * 0.5);
  42.     var y1 = rnd(Math.round(sh() * 0.78), Math.round(sh() * 0.82));
  43.     var y2 = rnd(Math.round(sh() * 0.18), Math.round(sh() * 0.22));
  44.     var d = rnd(420, 680);
  45.     try { auto.swip(x, y1, x, y2, d, 0); }
  46.     catch (e) { try { auto.swipe(x, y1, x, y2, d); } catch (e2) { printl("[ERR] 滑动失败: " + e2); } }
  47. }

  48. // ---------- 状态 ----------
  49. var ui = null, ctrls = {};
  50. var winX = 60, winY = 180;            // 小球初始位置
  51. var dragging = false, dragLastX = 0, dragLastY = 0, downX = 0, downY = 0;
  52. var running = false, round = 0;
  53. var ROUNDS = 15;                      // 自动刷轮数(到点自动收工)
  54. var worker = null;
  55. var hbOn = true;                      // 保活心跳开关:关窗时置 false,脚本自然结束
  56. var G_FLOATS = [];                    // 本脚本创建的 floatUI 实例(用于启动时清残留)

  57. // ---------- 布局:可拖动小球 + 可展开面板(竖向 LinearLayout,面板默认隐藏) ----------
  58. function buildXml() {
  59.     return '' +
  60.     '<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ' +
  61.     '  android:layout_width="wrap_content" android:layout_height="wrap_content" ' +
  62.     '  android:orientation="vertical" android:padding="0dp" ' +
  63.     '  android:background="#E61A2B3C">' +
  64.     // 小球(拖动把手 + 点按展开/收起)
  65.     '  <Button android:id="ball" android:layout_width="56dp" android:layout_height="56dp" ' +
  66.     '    android:text="AI" android:textColor="#FFFFFF" android:textSize="16sp" ' +
  67.     '    android:background="#16A34A" android:gravity="center"/>' +
  68.     // 展开面板(默认 GONE)
  69.     '  <LinearLayout android:id="panel" android:layout_width="200dp" android:layout_height="wrap_content" ' +
  70.     '    android:orientation="vertical" android:background="#E61A2B3C" android:padding="10dp" ' +
  71.     '    android:visibility="gone">' +
  72.     '    <TextView android:id="tip" android:layout_width="match_parent" android:layout_height="wrap_content" ' +
  73.     '      android:text="点「自动刷」开始,循环上滑" android:textColor="#86EFAC" android:textSize="12sp" android:paddingBottom="8dp"/>' +
  74.     '    <Button android:id="btnRun" android:layout_width="match_parent" android:layout_height="38dp" ' +
  75.     '      android:text="▶ 自动刷" android:textColor="#FFFFFF" android:textSize="13sp" android:background="#2563EB" android:layout_marginBottom="6dp"/>' +
  76.     '    <Button android:id="btnStop" android:layout_width="match_parent" android:layout_height="38dp" ' +
  77.     '      android:text="⏹ 收工" android:textColor="#FFFFFF" android:textSize="13sp" android:background="#B91C1C"/>' +
  78.     '  </LinearLayout>' +
  79.     '</LinearLayout>';
  80. }

  81. function moveTo(x, y) {
  82.     var screenW = sw(), screenH = sh();
  83.     if (x < 0) x = 0; if (y < 0) y = 0;
  84.     if (x > screenW - 60) x = screenW - 60;
  85.     if (y > screenH - 60) y = screenH - 60;
  86.     winX = x; winY = y;
  87.     try { ui.setPosition(x, y); } catch (e) {}
  88. }

  89. // 展开 / 收起面板
  90. function togglePanel() {
  91.     var V = resolveView();
  92.     try {
  93.         if (V && V.GONE !== undefined && ctrls.panel && ctrls.panel.setVisibility) {
  94.             var vis = ctrls.panel.getVisibility();
  95.             ctrls.panel.setVisibility(vis === V.VISIBLE ? V.GONE : V.VISIBLE);
  96.             printl(vis === V.VISIBLE ? '&#128316; 面板已收起' : '&#128317; 面板已展开');
  97.         }
  98.     } catch (e) { printl('⚠ 展开/收起失败: ' + e); }
  99. }

  100. // 后台循环刷(子线程里跑,不直接碰 UI)
  101. function loopSwipe() {
  102.     while (running && round < ROUNDS) {
  103.         round++;
  104.         humanSwipeUp();
  105.         sleepMs(rnd(900, 1400));
  106.         // 回主线程刷小球 / 提示文字
  107.         try {
  108.             var t = new thread();
  109.             t.runOnUiThread(function () {
  110.                 try { if (ctrls.ball) ctrls.ball.setText(round + '/' + ROUNDS); } catch (e) {}
  111.                 try { if (ctrls.tip) ctrls.tip.setText('刷到第 ' + round + ' 次'); } catch (e) {}
  112.             });
  113.         } catch (e) {}
  114.     }
  115.     // 收尾:回主线程提示,3 秒后自动关窗并结束脚本
  116.     try {
  117.         var t2 = new thread();
  118.         t2.runOnUiThread(function () {
  119.             try { if (ctrls.ball) ctrls.ball.setText('✔'); } catch (e) {}
  120.             try { if (ctrls.tip) ctrls.tip.setText('已完成 ' + ROUNDS + ' 次,准备收工'); } catch (e) {}
  121.             setRunEnabled(true);     // 完成后恢复按钮(3 秒内可再次点击)
  122.             printl('&#127937; 自动刷完成,3 秒后关窗');
  123.             try { runTime.setTimeout(function () { try { ui.close(); } catch (e) {} hbOn = false; }, 3000); } catch (e) {}
  124.         });
  125.     } catch (e) {}
  126.     running = false;
  127. }

  128. // 切换「自动刷」按钮的启用/禁用与外观(运行时禁用并变灰,避免重复点击 / 给出明确反馈)
  129. function setRunEnabled(on) {
  130.     try {
  131.         if (!ctrls.btnRun) return;
  132.         ctrls.btnRun.setEnabled(on);
  133.         ctrls.btnRun.setClickable(on);
  134.         ctrls.btnRun.setText(on ? '▶ 自动刷' : '● 运行中');
  135.         try { ctrls.btnRun.setBackgroundColor(on ? 0xFF2563EB : 0xFF555555); } catch (e2) {}
  136.     } catch (e) {}
  137. }

  138. function cmdRun() {
  139.     if (running) return;
  140.     running = true; round = 0;
  141.     setRunEnabled(false);            // 运行时禁用按钮 + 显示"运行中"
  142.     printl('▶ 自动刷开始(共 ' + ROUNDS + ' 次上滑)');
  143.     worker = new thread();
  144.     worker.runJsCode(function () { loopSwipe(); }, '自动刷线程');
  145. }
  146. function cmdStop() {
  147.     running = false; hbOn = false;
  148.     setRunEnabled(true);             // 收工后恢复按钮(窗口随即关闭,留底防重开)
  149.     printl('⏹ 收工,关闭窗口');
  150.     try { if (worker && worker.isAlive()) worker.stop(); } catch (e) {}
  151.     try { ui.close(); } catch (e) {}
  152. }

  153. // 拖动 + 点按 二合一(绑在小球上:移动超阈值=拖动,几乎没动=点按展开)
  154. function setupDrag() {
  155.     var V = resolveView(), M = resolveMotionEvent();
  156.     if (!V || !M || !ctrls.ball || !ctrls.ball.setOnTouchListener) {
  157.         printl('⚠ 拖拽不可用(缺 View/MotionEvent),小球用初始位置(仍可点按展开)');
  158.         return;
  159.     }
  160.     try {
  161.         ctrls.ball.setOnTouchListener(new V.OnTouchListener({
  162.             onTouch: function (view, event) {
  163.                 try {
  164.                     switch (event.getAction()) {
  165.                         case M.ACTION_DOWN:
  166.                             dragging = false;
  167.                             downX = event.getRawX(); downY = event.getRawY();
  168.                             dragLastX = downX; dragLastY = downY;
  169.                             return true;
  170.                         case M.ACTION_MOVE: {
  171.                             var mx = event.getRawX(), my = event.getRawY();
  172.                             if (!dragging && (Math.abs(mx - downX) > 8 || Math.abs(my - downY) > 8)) dragging = true;
  173.                             if (dragging) {
  174.                                 moveTo(winX + (mx - dragLastX), winY + (my - dragLastY));
  175.                                 dragLastX = mx; dragLastY = my;
  176.                             }
  177.                             return true;
  178.                         }
  179.                         case M.ACTION_UP:
  180.                             if (!dragging) togglePanel();   // 视为点按 → 展开/收起
  181.                             dragging = false;
  182.                             return true;
  183.                     }
  184.                 } catch (e2) { return false; }
  185.                 return false;
  186.             }
  187.         }));
  188.         printl('✔ 小球可拖动、可点按展开');
  189.     } catch (e) { printl('⚠ 拖拽绑定失败: ' + e); }
  190. }

  191. // 保活心跳:主线程一空闲脚本就结束、窗口会被回收,故用定时器递归保活;
  192. // running 时持续保活,收工/完成后置 hbOn=false 自然结束。
  193. function heartbeat() {
  194.     if (!hbOn) return;
  195.     runTime.setTimeout(heartbeat, 1000);
  196. }

  197. function main() {
  198.     printl('===== ⑤ 悬浮操作球(可展开)+ 循环任务 =====');

  199.     // 启动前清掉上次残留的浮窗(跟踪本脚本创建的实例,逐个 ui.close())
  200.     for (var i = 0; i < G_FLOATS.length; i++) { try { G_FLOATS[i].close(); } catch (e) {} }
  201.     G_FLOATS = [];

  202.     ui = new floatUI(); G_FLOATS.push(ui);
  203.     ui.loadXML(buildXml());

  204.     ctrls.ball   = ui.findViewById('ball');
  205.     ctrls.panel  = ui.findViewById('panel');
  206.     ctrls.tip    = ui.findViewById('tip');
  207.     ctrls.btnRun   = ui.findViewById('btnRun');
  208.     ctrls.btnStop  = ui.findViewById('btnStop');

  209.     if (!ctrls.ball) { printl('✘ 小球控件未取到,设备可能不支持 floatUI'); return; }

  210.     setupDrag();
  211.     try { ctrls.btnRun.setOnClickListener(function () { try { cmdRun(); } catch (e) {} }); } catch (e) {}
  212.     try { ctrls.btnStop.setOnClickListener(function () { try { cmdStop(); } catch (e) {} }); } catch (e) {}

  213.     moveTo(winX, winY);
  214.     heartbeat();   // 启动保活
  215.     printl('小球已出现:拖动移位;点小球展开面板;点「自动刷」循环上滑;「收工」关窗');
  216. }

  217. main();
复制代码







欢迎光临 B2B网络软件 (http://bbs.niubt.cn/) Powered by Discuz! X3.2