更新记录
1.1.4(2026-10-14)
【修复】iOS 云打包编译失败
1.1.3(2026-10-13)
【修复】ios编译打包问题:适配性的问题处理
1.1.2(2026-10-13)
【新增】大面板高度自适应 【修复】iOS 端云打包编译失败问题
查看更多平台兼容性
uni-app(5.24)
| Vue2 | Vue2插件版本 | Vue3 | Vue3插件版本 | Chrome | Safari | app-vue | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | × | × | - | √ | 1.0.0 | 5.0 | 1.0.0 | 14 | 1.0.0 | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
全局悬浮窗 omni-float-window
纯 UTS 实现的双端原生悬浮窗插件(Android Kotlin / iOS Swift 由 UTS 编译生成),无 GPL 风险、可闭源商用。
支持全局悬浮、桌面后台悬浮(Android)、跨页面 / Tab 切换不消失、丝滑拖拽、自动左右贴边、贴边半隐藏,纯色 / 渐变 / 背景图全样式自定义。Vue 页面与 nvue 页面通用,不限制页面类型。
支持端:App-Android(5.0+,minSdk 21)、App-iOS(14.0+)| H5 / 小程序 / 鸿蒙不支持
为什么选它
- 真原生窗口:Android 使用
WindowManager(桌面悬浮为TYPE_APPLICATION_OVERLAY系统窗口),iOS 使用独立UIWindow(windowLevel 高于 alert 且不抢占 keyWindow),不依赖任何页面组件,页面刷新 / 路由跳转 / Tab 切换均不消失。 - 一套 API 双端一致:事件名、负载字段、参数单位由共享契约
interface.uts统一,Android / iOS 行为一致。 - 丝滑拖拽:Android
ValueAnimator/ iOS 插值动画,拖拽零卡顿;自动判断单击与拖拽(touchSlop),互不干扰。 - 贴边与半隐藏:松手自动吸附左 / 右边缘;静止约 0.7s 后约 40% 滑出屏幕半隐藏,触摸或点击自动展开。
- 全样式自定义:形状(圆形 / 圆角矩形 / 直角)、边框、纯色、线性 / 径向渐变、背景图(fill / fit / center / tile),全部动态修改即时生效,无需重建。
- 图片自动缓存:内存 + 磁盘两级缓存(应用沙盒 cache 目录),网络背景图 / 图标不会重复下载。
- 权限闭环:
checkPermission检测 →requestPermission自动跳转系统授权页 → 结果回调;未授权自动降级为应用内悬浮,不崩溃。 - 生命周期安全:
closeFloatWindow彻底销毁窗口、视图与回调,无残留、无内存泄漏。 - 隐私干净:不采集、不上传任何用户数据,全部逻辑本地执行。
快速上手
1. 最小可用示例(vue 或 nvue 页面均可)
import { showFloatWindow } from '@/uni_modules/omni-float-window'
showFloatWindow({
width: 90,
height: 90,
contentText: '悬浮窗',
onClick: (data) => {
uni.showToast({ title: '点击了悬浮窗', icon: 'none' })
}
})
2. Android 桌面后台悬浮(推荐先申请权限)
import { checkPermission, requestPermission, showFloatWindow } from '@/uni_modules/omni-float-window'
checkPermission((granted) => {
if (granted) {
showFloatWindow({ globalDesktop: true, contentText: '全局悬浮' })
} else {
requestPermission((ok) => {
// ok = true 已授权;false 用户拒绝(此时 show 会自动降级为应用内悬浮)
showFloatWindow({ globalDesktop: ok, contentText: '全局悬浮' })
})
}
})
Android 宿主需声明 SYSTEM_ALERT_WINDOW 权限(在 manifest.json → app-plus → distribute → android → permissions 中添加,插件 demo 工程已内置;云打包时插件会自动带入)。
3. 完整示例
插件内置 8 个功能分区的演示控制台:uni_modules/omni-float-window/demo/index.vue(主控台)、page-b.vue(Tab 存活测试)、page-c.nvue(nvue 兼容测试)。将本插件导入工程后即可直接运行。
API 方法(17 个)
| 方法 | 说明 |
|---|---|
showFloatWindow(options) |
显示悬浮窗(首次调用创建;已显示时等效 updateConfig 应用最新配置) |
hideFloatWindow() |
隐藏(保留配置与视图,再次 show 快速恢复) |
closeFloatWindow() |
关闭并彻底销毁,清除全部配置与回调 |
checkPermission(cb) |
检测悬浮窗权限,cb(granted: boolean);iOS 恒为 true |
requestPermission(cb) |
申请权限(Android 自动跳转系统授权页),cb(granted: boolean) |
setAlpha(alpha) |
整体透明度 0.0 ~ 1.0 |
setPosition(x, y) |
设置位置(dp,屏幕左上角原点),自动夹取屏幕边界 |
setSize(width, height) |
设置尺寸(dp),即时生效 |
setShape(shape) |
形状:circle / rounded_rect / square |
setBorder(width, color) |
边框(dp / 颜色字符串),width<=0 去除边框 |
setBackgroundColor(color) |
纯色背景(同时关闭渐变) |
setGradientColor(type, start, end) |
渐变背景:linear / radial |
setBackgroundImage(url, mode) |
背景图,mode:fill / fit / center / tile;url 空字符串清除 |
setContentText(text) |
中心文字,空字符串隐藏 |
setIcon(url) |
中心图标(文字上方),空字符串隐藏 |
updateConfig(options) |
局部更新:仅传需要修改的字段(含全部样式 / 行为 / 回调),即时生效 |
单位约定:所有尺寸 / 位置参数单位为 dp(iOS 上 1dp≈1pt);
textSize按 sp 渲染。 颜色约定:#RRGGBB不透明,#AARRGGBB含透明度(AA 为透明度,FF 不透明,与 Android 约定一致),#RGB精简写法。 图片地址:支持http(s)://、本地绝对路径、file://路径;Android 额外支持工程相对路径(如static/xx.png,自动转绝对路径)。
Props 参数表(FloatWindowOptions)
所有字段均可选。showFloatWindow 首次创建时生效;之后可通过 updateConfig 局部更新,无需重建悬浮窗。
基础
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| width | number | 90 | 宽(dp) |
| height | number | 90 | 高(dp) |
| defaultX | number | 贴右留 12dp | 初始位置 X(dp) |
| defaultY | number | 屏高 30% | 初始位置 Y(dp) |
| alpha | number | 1.0 | 整体透明度 0.0~1.0 |
| dragEnable | boolean | true | 是否允许拖拽 |
| autoAdsorb | boolean | true | 松手后自动吸附左 / 右边缘 |
| autoHideEdge | boolean | true | 吸附后静止 0.7s 半隐藏(约 40% 滑出屏幕),触摸 / 点击展开 |
| globalDesktop | boolean | false | 桌面后台悬浮开关,见下方说明 |
globalDesktop 说明
- Android
true:系统悬浮窗(API26+TYPE_APPLICATION_OVERLAY),退后台 / 回桌面仍显示,需要「显示在应用上层」权限;未授权时自动降级为应用内悬浮并触发onPermissionDenied。 - Android
false:应用内悬浮(TYPE_APPLICATION,挂在主 Activity 的 WindowManager),跨页面 / Tab 不消失,退到桌面不显示,无需任何权限。 - iOS:应用内全局 UIWindow 悬浮(跨页面不消失)。iOS 系统限制不支持退后台 / 桌面显示,此开关在 iOS 上不产生系统级差异。
- 运行中切换该开关会自动重建窗口(updateConfig 已处理)。
形状 / 边框
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| shape | string | rounded_rect | circle(以宽高较小者为直径)/ rounded_rect / square |
| borderRadius | number | 20 | 圆角半径(dp),rounded_rect 时生效 |
| borderWidth | number | 0 | 边框宽度(dp),0 为无边框 |
| borderColor | string | #80FFFFFF | 边框颜色 |
背景
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| bgColor | string | #E62979FF | 纯色背景(渐变开启时作为渐变底色) |
| bgGradientEnable | boolean | false | 渐变背景开关 |
| bgGradientType | string | linear | linear(左上→右下)/ radial(中心向外) |
| bgGradientStartColor | string | #FF2979FF | 渐变起始色 |
| bgGradientEndColor | string | #FF00C6A7 | 渐变结束色 |
| bgImage | string | "" | 背景图地址;空字符串清除 |
| bgImageMode | string | fill | fill 拉伸铺满 / fit 等比完整 / center 等比居中裁剪 / tile 平铺 |
背景图自动跟随形状裁切(圆形 / 圆角均生效)。
内容
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| contentText | string | 悬浮窗 | 中心文字,空字符串隐藏 |
| textSize | number | 13 | 文字大小(sp) |
| textColor | string | #FFFFFFFF | 文字颜色 |
| textFontWeight | string | bold | normal / bold |
| icon | string | "" | 中心图标(文字上方),空字符串隐藏 |
| iconWidth | number | 28 | 中心图标宽(dp) |
| iconHeight | number | 28 | 中心图标高(dp) |
| leftIcon | string | "" | 左侧图标,空字符串隐藏 |
| rightIcon | string | "" | 右侧图标,空字符串隐藏 |
| padding | number | 8 | 内容内边距(dp) |
支持图文混排:中心图标 + 文字垂直排列、左右图标独立控制,全部可动态更新。
点击展开(单击放大查看更多信息)
设置 expandContentText 后启用:单击小窗 → 悬浮窗放大到屏幕正中央,显示更详细的内容;再操作即可收起。适合行情报价、消息详情等「小窗简略 + 大窗详情」场景。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| expandContentText | string | "" | 展开后大面板的内容,支持 \n 换行(行数不限);空字符串表示关闭点击展开 |
| expandWidth | number | 220 | 大面板宽(dp) |
| expandHeight | number | 300 | 大面板高(dp);expandAutoHeight = true 时不生效 |
| expandAutoHeight | boolean | true | 大面板高度随内容自适应撑开(实测内容高度,紧凑不留空白);设为 false 使用固定 expandHeight;通过 updateConfig 更新内容后自适应高度自动重算 |
交互约定(双端一致)
- 单击小窗 → 放大到屏幕正中央,显示
expandContentText(约 0.3s 双击判定后触发) - 单击大面板 → 立即收起,恢复原尺寸 / 原内容 / 原位置
- 双击小窗 → Android 桌面悬浮模式下返回应用界面(App 在后台时);iOS 无桌面悬浮,双击无动作
- 展开期间禁用拖拽与长按;展开 / 收起会触发
onConfigChanged(action为expand/collapse) - 收起后重新展开显示的是
expandContentText的最新值,可用updateConfig({ expandContentText: '...' })动态更新大面板内容
showFloatWindow({
width: 90, height: 60,
contentText: '黄金 512.30\n白银 8.15', // 小窗:简略报价
expandWidth: 240,
expandHeight: 320,
expandContentText: '黄金 Au99.99 512.30 +1.2%\n白银 Ag99.99 8.15 -0.3%\n铂金 Pt 221.60 +0.8%\n—— 单击面板收起 ——'
})
换行符说明:
contentText与expandContentText的换行必须是英文半角\n(反斜杠 + 小写 n,代码字符串直接写'\n'即可);中文输入法的全角\n不生效。
事件(10 个)
回调负载统一为 UTSJSONObject(JS 侧即普通对象)。
| 事件 | 负载 | 说明 |
|---|---|---|
| onClick | {x, y} |
单击(与拖拽自动区分,x/y 为悬浮窗中心点 dp 坐标) |
| onLongPress | {x, y} |
长按约 500ms |
| onDragStart | {x, y} |
开始拖拽(位移超过 touchSlop 触发一次) |
| onDragEnd | {side, x} |
拖拽结束,side = left / right / none |
| onAdsorb | {side, x} |
自动吸附完成,side = left / right |
| onShow | {} |
悬浮窗显示 |
| onHide | {} |
悬浮窗隐藏 |
| onPermissionGranted | {granted:true} |
权限已授予 |
| onPermissionDenied | {granted:false} |
权限被拒绝(Android 桌面悬浮将自动降级为应用内悬浮) |
| onConfigChanged | {action, x} |
任意 set 方法 / updateConfig 生效后触发,action 为方法名;点击展开 / 收起时为 expand / collapse |
注意事项
- UTS 插件含原生代码,标准基座无法运行,请先在 HBuilderX 中「制作自定义基座」或云打包后真机测试。
- iOS 因系统限制无法实现退后台 / 桌面悬浮(所有 iOS 插件均如此),
globalDesktop仅 Android 生效,文档如实标注,请按需选型。 - Android 未授权
globalDesktop=true时自动降级为应用内悬浮,并通过onPermissionDenied通知,不会崩溃。 - 请在合适时机调用
closeFloatWindow()彻底销毁悬浮窗(Demo 在页面 onUnload 中演示)。App 退出时窗口随进程销毁,无残留。 - 刘海屏 / 挖孔屏:位置计算基于窗口可用区域,拖拽边界已适配;如需严格避开状态栏可将 defaultY 设置为 ≥ 40。
- 网络背景图请确保域名可访问;图片默认缓存到应用沙盒 cache 目录,卸载 App 自动清理。
常见问题
Q:悬浮窗会被微信等桌面 App 覆盖吗?
A:Android globalDesktop=true 使用系统级窗口,回桌面 / 打开其他 App 仍显示;false 或 iOS 时仅在自家 App 内显示。
Q:拖拽时误触 onClick? A:不会。位移超过 8dp 判定为拖拽,单击事件被抑制;松手静止后才可能触发吸附与半隐藏。
Q:如何让悬浮窗一直不被半隐藏?
A:updateConfig({ autoHideEdge: false }),贴边吸附保留、不再滑出。
Q:运行报 undefined is not an object (evaluating '_omniFloatWindow.xxx')?
A:当前运行基座里没有编译进本 UTS 插件(Android / iOS 同理)。UTS 插件不能使用标准基座运行:请「发行 → 原生App-云打包 → 打自定义调试基座」重新打包并安装,运行时勾选「使用自定义基座运行」。若基座是在安装本插件之前打的,或插件升级后未重打基座,也会报此错误——修改工程版本号后重新打包即可。
Q:可以同时创建多个悬浮窗吗? A:当前版本为单实例设计(全局唯一悬浮窗),重复 show 等效更新配置。
Q:contentText / expandContentText 里的 \n 显示成了文字?
A:换行必须是英文半角 \n(反斜杠+n)。代码里写 contentText: '第一行\n第二行' 直接生效;若是用户在输入框里手打 \n,需要先把字符串里的 \n 替换成真实换行符再传入(demo 页的 toRealNewline 方法有现成实现,含全角\n与带引号写法的容错)。
更新日志
见 changelog.md。
授权与支持
- 纯自研代码,不含 GPL / LGPL 组件,无传染风险。
- 支持双授权:普通授权(加密、仅云打包)与源码授权(可离线打包 / 二次开发),详见 license.md。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 28
赞赏 0
下载 12716117
赞赏 1958
赞赏
京公网安备:11010802035340号