这是关于悬浮窗的问题。如何让悬浮窗能够缩小成一个靠近屏幕边缘的小图标?我使用floaty.window创建了悬浮窗,使用setAdjustEnabled方法以后仅仅只是给悬浮窗增加了三个按钮,可以拖动改变大小,但是不能让它缩小成一个更小一点的图标。我看其他人的脚本的悬浮窗有一个缩小化的按钮,可以缩小成一个看上去像一个控制台的图标,很小且简洁,可以所以拖动到屏幕的任何边缘,不会过多遮挡内容。点击图标后可以恢复悬浮窗,里面还可以实时显示toast的历史记录。这种缩小化是怎么做到的?那个脚本的悬浮窗背景是半透明的黑色,样式看上是预制的,如何创建这样的悬浮窗?

SilverFox0-6 · 7 小时前

回答

Hamibot AI
1
· 7 小时前

悬浮窗缩小成小图标的功能并不是 floaty 模块自带的原生参数,而是通过脚本逻辑自定义实现的。setAdjustEnabled(true) 仅用于启用系统默认的拖拽调整大小手柄,无法实现最小化为图标并隐藏主窗口的效果。

要实现你描述的“控制台图标”效果,核心思路是维护两个状态:正常窗口模式图标模式。通常做法是创建两个悬浮窗(一个主窗口,一个小图标),或者动态修改同一个窗口的大小和内容。为了性能和体验,推荐创建两个窗口进行切换显示。

以下是实现该功能的完整方案和代码示例。代码已针对 Hamibot 的 Rhino 引擎进行了兼容性处理(无箭头函数、无默认参数)。

实现原理

  1. 双窗口管理:创建一个较大的主窗口用于显示详细日志,创建一个较小的悬浮窗作为“图标”。
  2. 样式定制:使用 XML 布局文件定义半透明黑色背景(bg="#80000000")和紧凑的控件。
  3. 状态切换:点击主窗口的“最小化”按钮时,隐藏主窗口并显示图标;点击图标时,隐藏图标并恢复主窗口。
  4. 日志记录:手动维护一个日志数组,将 toastLog 的内容同步到悬浮窗的文本控件中。

代码示例

// 文档地址 https://docs.hamibot.com/

// 检查悬浮窗权限
if (!android.provider.Settings.canDrawOverlays(context)) {
    toast("请授予悬浮窗权限");
    app.startActivity({
        action: "android.settings.action.MANAGE_OVERLAY_PERMISSION"
    });
}

// 存储日志的数组
var logList = [];
var maxLogCount = 20; // 最多保留多少条日志

// 初始化主窗口
var mainWindow = floaty.rawWindow(
    <frame gravity="center" bg="#80000000" w="*" h="wrap_content">
        <vertical padding="10">
            <text id="logText" textSize="14sp" textColor="#ffffff" h="auto"/>
            <button id="minBtn" text="最小化" w="wrap_content" h="wrap_content" margin="10 0 0 0"/>
        </vertical>
    </frame>
);

// 初始化图标窗口
var iconWindow = floaty.rawWindow(
    <frame gravity="center" bg="#FF000000" w="40dp" h="40dp">
        <text id="iconText" text="H" textSize="18sp" textColor="#ffffff"/>
    </frame>
);

// 设置初始位置
mainWindow.setPosition(100, 100);
iconWindow.setPosition(100, 100);

// 更新日志显示的函数
function updateLogDisplay() {
    ui.run(function () {
        var text = "";
        for (var i = 0; i < logList.length; i++) {
            text += logList[i] + "\n";
        }
        mainWindow.logText.setText(text);
    });
}

// 模拟添加日志(实际使用时替换为你的业务逻辑)
function addLog(msg) {
    logList.push(msg);
    if (logList.length > maxLogCount) {
        logList.shift();
    }
    updateLogDisplay();
    toastLog(msg);
}

// 最小化按钮点击事件
mainWindow.minBtn.click(function () {
    mainWindow.hide();
    iconWindow.show();
});

// 图标点击事件(恢复主窗口)
iconWindow.click(function () {
    iconWindow.hide();
    mainWindow.show();
});

// 保持脚本运行
setInterval(function () {}, 1000);

// 测试日志输出
addLog("脚本启动");
addLog("悬浮窗已就绪");

关键细节说明

  1. 半透明背景:在 XML 布局中使用 bg="#80000000"。前两位 80 代表透明度(十六进制),后六位 000000 代表黑色。你可以调整前两位数值来改变透明度(例如 40 更透明,FF 完全不透明)。
  2. UI 线程操作:所有涉及修改悬浮窗 UI 的操作(如 setText, show, hide)必须在 ui.run() 中执行,否则可能报错或无效。
  3. Rhino 兼容性:代码中使用了 var 声明变量,使用 function 定义回调,避免使用箭头函数 =>const/let,确保在 Hamibot 的 JavaScript 引擎中稳定运行。
  4. 日志同步toastLog 会将消息打印到控制台,但不会自动同步到悬浮窗。你需要自己编写逻辑(如上面的 addLog 函数)将消息存入数组并更新界面。
  5. 生命周期:脚本停止运行时悬浮窗会自动关闭。如果需要在后台长时间运行,请确保脚本没有被系统杀死,并使用 setInterval 保持循环。

最佳实践建议

  • 性能优化:如果日志更新非常频繁,建议在 updateLogDisplay 中加入节流控制,避免每秒刷新多次导致 UI 卡顿。
  • 拖动支持:上述代码未包含拖动逻辑。如果需要拖动,可以在 frame 上监听 touchDowntouchMove 事件,结合 setPosition 实现自定义拖动,这比 setAdjustEnabled 更灵活。
  • 资源释放:脚本结束前调用 mainWindow.close()iconWindow.close() 可以确保资源被正确释放。

这种方案完全由脚本控制,因此你可以自由定制图标的形状、颜色和交互方式,达到你想要的“简洁控制台”效果。

ℹ️ 内容由 AI 生成,可能不准确,请注意核实