更新记录
1.0.2(2026-11-05)
更新说明
1.0.1(2026-11-05)
- 支持按需启用 Android、鸿蒙和 iOS 的悬浮显示功能,插件接入后需主动开启。
- iOS 使用画中画方案,需由接入项目配置所需的后台能力。
- 关闭某个平台的功能后,停止该平台的悬浮显示和相关操作。
平台兼容性
uni-app x(5.33)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 | 微信小程序 |
|---|---|---|---|---|---|---|---|---|
| × | × | 5.0 | 1.0.2 | 15 | 1.0.2 | 12 | 1.0.2 | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| √ | √ | √ | √ |
图片悬浮窗插件
pow-floatwindow 适用于 uni-app x 项目,支持蒸汽模式
主要功能是
- app退到后台时展示系统级悬浮窗
- (安卓和鸿蒙)app退到后台时,使用api让app回到前台(比如来订单了自动让app到前台)
接入准备
- 将
pow-floatwindow导入项目 - Android 和 iOS 都需要在导入本插件后,打自定义基座,并选择自定义调试基座运行项目。
- iOS 需完成本文的“iOS 配置”;鸿蒙需完成“鸿蒙配置”中的页面注册、生命周期接入和签名授权。
- 在应用启动时初始化插件,再调用业务接口。
| 平台 | 使用条件 | 接口使用差异 |
|---|---|---|
| Android 5.0(API 21)及以上 | 获取系统悬浮窗授权 | 支持设置位置、拖动,以及请求返回前台。 |
| 鸿蒙 API 12 及以上 | 获取系统悬浮窗受限权限及签名授权 | 支持设置位置、拖动,以及请求返回前台;需接入悬浮窗承载页面。 |
| iOS 15 及以上 | 设备支持画中画 | 使用画中画显示图片,位置和尺寸由系统管理;用户可通过系统画中画按钮返回应用。 |
初始化:initFloatWindow
在 App.uvue 中接入以下代码;已有生命周期回调时,将相应调用合并进去:
<script setup lang="uts">
// #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
import { initFloatWindow } from '@/uni_modules/pow-floatwindow'
// #endif
// #ifdef APP-HARMONY
import { notifyAppShow, notifyAppHide } from '@/uni_modules/pow-floatwindow'
// #endif
onLaunch(() => {
// #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
const enabled = initFloatWindow({
iosEnable: true,
androidEnable: true,
harmonyEnable: true
})
console.log('当前平台插件是否已启用', enabled)
// #endif
})
onAppShow(() => {
// #ifdef APP-HARMONY
notifyAppShow()
// #endif
})
onAppHide(() => {
// #ifdef APP-HARMONY
notifyAppHide()
// #endif
})
</script>
initFloatWindow(options: FloatWindowInitOptions): boolean
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
iosEnable |
boolean |
是 | 是否启用 iOS 功能。还需在应用中配置 UIBackgroundModes 的 audio 项。 |
androidEnable |
boolean |
是 | 是否启用 Android 功能。 |
harmonyEnable |
boolean |
是 | 是否启用鸿蒙功能。 |
每个平台只读取对应开关,可按项目需要关闭其他平台。返回 true 表示当前平台插件已启用,授权状态和设备支持情况仍需分别查询。
未初始化或当前平台未启用时,操作接口不会执行,也不会调用回调;getCapabilities() 和 getFloatWindowState() 返回 null。 iOS 缺少后台音频配置时,即使传入 iosEnable: true,初始化也会返回 false。关闭已启用的平台会清理悬浮窗及事件监听,重新启用后需重新注册监听。
快速调用:检查授权并显示图片
以下代码放在业务页面的 <script setup lang="uts"> 中,在用户需要显示图片时调用 openImageWindow()。请先将图片放到自己项目的 /static/float-image.png。后续调用示例也在业务页面中使用;如同时编译 Web 等其他平台,请使用 APP-ANDROID || APP-IOS || APP-HARMONY 条件编译包裹插件导入及相关调用。
import {
getCapabilities, getPermissionStatus, requestPermission, showFloatWindow
} from '@/uni_modules/pow-floatwindow'
import type { FloatWindowResult } from '@/uni_modules/pow-floatwindow/utssdk/interface'
function openImageWindow() {
const capabilities = getCapabilities()
if (capabilities == null || !capabilities.supported) {
console.log('请先启用插件,并确认设备支持悬浮显示')
return
}
getPermissionStatus((res: FloatWindowResult) => {
if (res.errCode != 0) {
console.log(res.msg)
return
}
if (res.data?.getBoolean('granted') != true) {
requestPermission((permissionRes: FloatWindowResult) => {
console.log(permissionRes.msg)
})
return
}
showFloatWindow({
source: '/static/float-image.png',
width: 64,
height: 64,
x: 20,
y: 240,
draggable: true
}, (showRes: FloatWindowResult) => {
console.log(showRes.errCode, showRes.msg)
})
})
}
Android 首次调用可能会打开系统授权设置。用户返回应用后,再调用 openImageWindow(),或在页面 onShow 中重新检查权限。授权请求的回调不代表用户已经完成授权。
建议在应用前台调用显示接口,确认窗口出现后再切换到后台。iOS 必须在前台启动画中画,并等待显示成功的回调。
接口说明
下列带回调的接口均使用 FloatWindowCallback,即 (result: FloatWindowResult) => void。接口从 @/uni_modules/pow-floatwindow 导入,类型从 @/uni_modules/pow-floatwindow/utssdk/interface 导入。
查询平台能力:getCapabilities
getCapabilities(): FloatWindowCapabilities | null
| 返回字段 | 类型 | 说明 |
|---|---|---|
mode |
string |
当前平台使用的悬浮显示方式。 |
supported |
boolean |
当前实现或设备是否支持;不代表已经获得权限。 |
permissionRequired |
boolean |
是否需要悬浮窗权限。 |
positionControl |
boolean |
是否支持通过接口设置位置。 |
dragging |
boolean |
是否支持用户拖动窗口。 |
bringToFront |
boolean |
是否提供返回前台请求;不保证系统一定允许。 |
minVersion |
number,可选 |
最低系统版本或 API 级别。 |
调用位置调整、返回前台等接口前,可先检查对应字段。iOS 的 positionControl 和 bringToFront 均为 false。
查询和申请权限
getPermissionStatus(callback: FloatWindowCallback):查询当前权限状态,通过res.data?.getBoolean('granted')判断是否已授权。errCode == 0仅表示查询成功。requestPermission(callback: FloatWindowCallback):申请或检查当前平台的使用资格。
| 平台 | requestPermission 的行为 |
|---|---|
| Android | 未授权时打开系统悬浮窗设置,返回 errCode: 1,并在 data.settingsOpened 中标记已打开设置;返回应用后应重新查询权限。已授权时返回 0。 |
| 鸿蒙 | 检查系统悬浮窗受限权限,不会弹出普通运行时授权窗口。未获授权时返回 -5,需按“鸿蒙配置”处理。 |
| iOS | 检查设备是否支持画中画,无单独的悬浮窗授权弹窗。支持时返回 0,不支持时返回 -5。 |
权限结果的 data.granted 表示是否已授权。Android、iOS 查询结果还提供 required;鸿蒙提供 supported 和 permission,申请结果还提供 requiresEligibleSignature。
iOS 的 getPermissionStatus 返回 granted: true、required: false;设备是否支持画中画应使用 getCapabilities().supported 或 requestPermission 判断。
显示悬浮窗:showFloatWindow
showFloatWindow(options: FloatWindowOptions, callback: FloatWindowCallback)
| 参数 | 类型 | 必填 | 默认值 / 说明 |
|---|---|---|---|
source |
string |
是 | 图片地址,不能为空。可使用 /static/ 下的图片、本地图片文件路径或网络图片地址,网络图片建议使用 HTTPS。 |
width |
number |
否 | 默认 64,建议传正数。 |
height |
number |
否 | 默认 64,建议传正数。 |
x |
number |
否 | 左上角横坐标,省略时靠屏幕右侧;传入时使用非负数。 |
y |
number |
否 | 左上角纵坐标,省略时位于屏幕中部附近;传入时使用非负数。 |
draggable |
boolean |
否 | 默认 true,是否允许拖动。 |
Android 的尺寸和坐标单位为 dp,鸿蒙为 px。iOS 只使用 source,其余参数不控制画中画窗口;窗口尺寸、位置和拖动交互由系统管理。
Android 的显示回调表示显示请求已提交,图片仍可能加载失败;需要结合窗口事件和状态查询处理后续结果。鸿蒙的显示回调依赖承载页面上报图片加载结果。iOS 在画中画实际启动后返回显示成功。
替换图片:setFloatWindowImage
setFloatWindowImage(source: string, callback: FloatWindowCallback)
import { setFloatWindowImage } from '@/uni_modules/pow-floatwindow'
setFloatWindowImage('/static/another-image.png', (res) => {
console.log(res.errCode, res.msg)
})
source 的填写方式与显示接口相同。建议在悬浮窗已显示时调用;更新失败时根据回调处理,已显示的图片会尽量保留。此接口不负责打开悬浮窗,需要显示时仍应调用 showFloatWindow 并传入所需图片地址。
调整位置:setFloatWindowPosition
setFloatWindowPosition(position: FloatWindowPosition, callback: FloatWindowCallback)
import { getCapabilities, setFloatWindowPosition } from '@/uni_modules/pow-floatwindow'
const capabilities = getCapabilities()
if (capabilities != null && capabilities.positionControl) {
setFloatWindowPosition({ x: 40, y: 200 }, (res) => {
console.log(res.errCode, res.msg)
})
}
x、y 均为必填的非负数,单位与显示接口一致。建议在窗口显示后调用,超出屏幕可用范围的位置会被限制在可用范围内。iOS 调用此接口返回 -5。
查询状态:getFloatWindowState
getFloatWindowState(): FloatWindowState | null
import { getFloatWindowState } from '@/uni_modules/pow-floatwindow'
const state = getFloatWindowState()
if (state != null) {
console.log('是否显示', state.visible)
console.log('当前图片', state.source)
}
| 返回字段 | 类型 | 说明 |
|---|---|---|
visible |
boolean |
当前记录的悬浮显示状态。 |
permissionGranted |
boolean |
当前记录的授权状态;需要重新确认时调用 getPermissionStatus。 |
source |
string |
当前记录的图片地址,可能是转换后的本地路径。 |
x、y |
number |
当前坐标,Android 为 dp、鸿蒙为 px。 |
width、height |
number |
当前尺寸,Android 为 dp、鸿蒙为 px。 |
iOS 的坐标和尺寸字段固定返回 0,不能据此读取系统画中画窗口的实际位置和大小。状态可能随异步操作更新,宜在操作回调或窗口事件后查询。
隐藏和销毁悬浮窗
hideFloatWindow(callback: FloatWindowCallback):结束当前显示;需要再次显示时重新调用showFloatWindow(options, callback)。destroyFloatWindow(callback: FloatWindowCallback):结束当前显示并释放悬浮窗资源,用于业务结束时清理。
import { hideFloatWindow, destroyFloatWindow } from '@/uni_modules/pow-floatwindow'
function hideImageWindow() {
hideFloatWindow((res) => console.log(res.errCode, res.msg))
}
function finishImageWindow() {
destroyFloatWindow((res) => console.log(res.errCode, res.msg))
}
隐藏或销毁不等于关闭平台开关。如需停止使用插件,可再次调用 initFloatWindow,将当前平台开关设为 false。如果需要跨页面继续显示,请根据业务结束时机清理,不要在每次页面离开时自动销毁。
请求返回前台:requestBringToFront
requestBringToFront(options: FloatWindowBringToFrontOptions, callback: FloatWindowCallback)
import { getCapabilities, requestBringToFront } from '@/uni_modules/pow-floatwindow'
const capabilities = getCapabilities()
if (capabilities != null && capabilities.bringToFront) {
requestBringToFront({ delayMs: 5000 }, (res) => {
console.log(res.errCode, res.msg)
})
}
delayMs 为可选的等待时间,单位毫秒,默认 0;传入 {} 表示立即请求。需要延时返回时,可以在应用前台安排请求,再切换到后台。
Android 和鸿蒙的返回前台请求受系统限制,应以回调结果判断,不能保证每次成功。鸿蒙需接入 notifyAppShow()、notifyAppHide() 才能正确跟踪应用前后台状态。iOS 调用此接口返回 -5,应由用户点击系统画中画中的返回应用按钮。
监听和取消监听事件
onFloatWindowEvent(callback: FloatWindowEventCallback):注册事件监听。offFloatWindowEvent(callback: FloatWindowEventCallback):取消指定监听,必须传入注册时的同一个函数。
import { onFloatWindowEvent, offFloatWindowEvent } from '@/uni_modules/pow-floatwindow'
import type { FloatWindowEvent } from '@/uni_modules/pow-floatwindow/utssdk/interface'
const handleFloatWindowEvent = (event: FloatWindowEvent): void => {
const type = event.getString('type')
const message = event.getString('message')
console.log('悬浮窗事件', type, message)
}
onLoad(() => {
onFloatWindowEvent(handleFloatWindowEvent)
})
onUnload(() => {
offFloatWindowEvent(handleFloatWindowEvent)
})
事件对象包含 type,部分事件还会提供 message。避免反复注册同一个监听;需要跨页面持续接收事件时,可在应用级统一管理。
事件 type |
含义 | 可能触发的平台 |
|---|---|---|
show |
窗口开始显示,不单独代表图片已经加载成功。 | Android、鸿蒙、iOS |
hide |
调用隐藏接口后结束显示。 | Android、鸿蒙、iOS |
destroy |
销毁悬浮窗。 | 鸿蒙、iOS |
click |
点击悬浮图片。 | Android、鸿蒙 |
dragEnd |
结束拖动。 | Android、鸿蒙 |
systemClose |
窗口被系统或用户关闭。 | Android、iOS |
restore |
用户通过画中画返回应用。 | iOS |
error |
图片加载或画中画启动等异常。 | Android、iOS |
各平台不会触发全部事件;判断某次调用的结果时,应同时处理该接口的回调。例如 Android 销毁时不发送 destroy 事件。
回调结果与错误处理
type FloatWindowResult = {
errCode: number
msg: string
platform: string
data?: UTSJSONObject
}
platform 为 android、harmony 或 ios。data 根据接口提供附加信息,读取前需判空。业务分支应使用 errCode 和 data,不要依赖 msg 的固定文案。
errCode |
含义 / 处理方式 |
|---|---|
0 |
本次操作或查询成功,具体含义以接口说明为准。 |
1 |
Android 已打开授权设置,等待用户操作后重新检查权限。 |
-1 |
参数不正确,例如图片地址为空、位置为负数。 |
-2 |
Android 悬浮窗权限未授予或不可用。 |
-3 |
Android 当前没有可用的应用界面,请在应用界面可用时调用。 |
-4 |
操作失败、请求取消或等待超时,结合 msg 处理。 |
-5 |
当前平台、设备、权限条件不支持本次操作,或 iOS 画中画启动失败。 |
-6 |
图片加载或更新失败,请检查图片地址、文件和网络。 |
iOS 配置
- 导入插件
- 初始化时传入
iosEnable: true。 - 重新打包 iOS 自定义调试基座并安装,选择该基座运行。后台能力配置变更后,仅更新页面代码不能使配置生效。
- 使用支持画中画的 iOS 15 及以上设备,并确认系统画中画功能可用。
- 在应用前台调用
showFloatWindow,等待成功回调后再切换到后台。
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
该片段放在 Info.plist 的 <dict> 内。插件不会替宿主应用自动开启后台音频能力;应用需明确完成上述配置。正式发布前,请确认图片画中画的用途符合目标分发渠道的要求。
鸿蒙配置
注册悬浮窗承载页面
将仓库中的 pages/floatwindow/index.uvue 复制到自己项目的同名路径,并在 pages.json 的 pages 数组中添加以下配置。该页面是鸿蒙悬浮窗显示图片所需的承载页面,无需在业务中通过页面跳转打开:
{
"path": "pages/floatwindow/index",
"style": {
"navigationStyle": "custom"
}
}
请保留 pages/floatwindow/index 路径,以及页面中的图片加载和交互回调。同时按初始化示例,在 App.uvue 的应用前后台生命周期中调用 notifyAppShow 和 notifyAppHide。
| 接口 | 接入位置 / 用途 |
|---|---|
notifyAppShow() |
鸿蒙专用,在应用进入前台时调用,用于确认返回前台请求的结果。 |
notifyAppHide() |
鸿蒙专用,在应用进入后台时调用,用于更新前后台状态。 |
dispatchFloatWindowEvent(type: string) |
承载页面转发点击、拖动结束等事件;普通业务页面通常只需注册事件监听。 |
dispatchFloatWindowImageLoad(revision: number, success: boolean) |
承载页面上报图片加载结果;保留所提供页面的调用即可,业务页面不要手动上报。 |
处理“运行所需的权限没有签名授权”
本插件需要 ohos.permission.SYSTEM_FLOAT_WINDOW。应用声明此权限,但签名 Profile 没有包含相应授权时,设备会拒绝安装。处理步骤如下:
- 在华为 AppGallery Connect(AGC)中,为自己的应用申请系统悬浮窗受限权限,并按要求说明使用场景。能否获得授权,以华为审核结果为准。
- 获批后,重新生成并下载包含该权限授权的调试 Profile(
.p7b),确认与项目包名、签名证书及当前调试设备匹配。 - 在 HBuilderX 项目的鸿蒙签名配置中替换 Profile;如果更换了签名证书或密钥,一并更新对应配置。
- 重新打包并运行到鸿蒙设备。安装成功后,初始化插件,调用
getPermissionStatus检查授权,再调用showFloatWindow。
正式发布也需要使用包含相应授权的发布签名资料。普通运行时授权弹窗、手机设置开关或重新生成普通调试签名不能替代此授权;删除系统悬浮窗权限声明会导致悬浮窗功能无法使用。

收藏人数:
购买源码授权版(
试用
使用 HBuilder 导入示例项目
赞赏(0)
下载 2679
赞赏 0
下载 12748793
赞赏 1959
赞赏
京公网安备:11010802035340号