更新记录
1.0.0(2026-09-11)
首次发布。
新增
- 全局悬浮窗核心:Android WindowManager(应用内
TYPE_APPLICATION/ 桌面悬浮TYPE_APPLICATION_OVERLAY),iOS 独立UIWindow(windowLevel=2001,不抢占 keyWindow)。 - 跨页面 / Tab 切换不消失;Android 支持退后台 / 桌面后台悬浮(需权限,未授权自动降级并回调)。
- 丝滑拖拽(Android
ValueAnimator/ iOS 插值动画),单击与拖拽自动区分(touchSlop 8dp)。 - 自动左右贴边吸附、贴边半隐藏(约 40% 滑出屏幕,0.7s 后触发)、触摸 / 点击自动展开。
- 全样式自定义:形状(circle / rounded_rect / square)、边框、纯色背景、线性 / 径向渐变(CAGradientLayer / GradientDrawable)、背景图(fill / fit / center / tile)、圆角裁切、边框。
- 内容自定义:中心文字(大小 / 颜色 / 字重)、中心图标、左右侧图标、图文混排、内边距,全部动态更新即时生效。
- 权限闭环:
checkPermission/requestPermission+onPermissionGranted/onPermissionDenied回调。 - 10 个生命周期与交互事件,负载统一 UTSJSONObject,双端一致。
- 图片内存 + 磁盘两级缓存(应用沙盒 cache 目录),网络图片不重复下载。
- Demo 演示工程:主控台(8 大功能区)、Tab 页 B 存活测试、nvue 页 C 兼容测试。
平台兼容性
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) |
支持图文混排:中心图标 + 文字垂直排列、左右图标独立控制,全部可动态更新。
事件(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 为方法名 |
注意事项
- 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:可以同时创建多个悬浮窗吗? A:当前版本为单实例设计(全局唯一悬浮窗),重复 show 等效更新配置。
更新日志
见 changelog.md。
授权与支持
- 纯自研代码,不含 GPL / LGPL 组件,无传染风险。
- 支持双授权:普通授权(加密、仅云打包)与源码授权(可离线打包 / 二次开发),详见 license.md。

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