自定义悬浮操作球可拖动小球点按展开
自定义悬浮操作球可拖动小球点按展开
// =============================================================
// 案例 ⑤悬浮操作球(可拖动小球 + 点按展开)+ 循环任务
// -------------------------------------------------------------
// 这是 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(" 滑动失败: " + 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.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();
页:
[1]