App端无法用position: fixed实现真悬浮,因iOS/Android原生容器不支持Web层fixed稳定渲染;必须通过原生插件(如Ba-FloatWindow)或自研WindowManager/UIWindow实现。
position: fixed 实现不了真悬浮?不能。App端(尤其iOS)的 WebView 容器不支持 position: fixed 在原生层之上稳定渲染,页面滚动、软键盘弹出、横竖屏切换时会错位甚至消失。这不是 CSS 写得不对,而是 uni-app 的 App 编译目标(iOS/Android 原生容器)根本没把 Web 层的 fixed 当“真固定”。你看到它在 H5 或小程序里能动,不代表 App 端也行。
实操建议:
• 必须走原生插件路线,比如 Ba-FloatWindow 或自研 Android WindowManager / iOS UIWindow 级悬浮;
• 不要试图在 App.vue 里靠 CSS “硬撑”,那只是开发阶段的假象;
• 若仅需轻量提示(非拖拽、非跨页面穿透),可退而求其次用 uni.showToast + 自定义 icon,但不属于“气泡悬浮窗”范畴。
Android 8.0+ 强制要求申请 MANAGE_OVERLAY_PERMISSION,且必须在运行时跳转系统设置页让用户手动开启——uni-app 的 plus.android.requestPermissions 无法替代这一步。漏掉它,WindowManager.addView() 会静默失败,logcat 里只报 BadTokenException 或直接黑屏无反应。
实操建议:
• 在插件的 onStartCommand 中判断 Build.VERSION.SDK_INT >= Build.VERSION_CODES.O,严格使用 TYPE_APPLICATION_OVERLAY;
• 调用插件前,先执行 uni.openSetting() 并检查 scope.systemSetting 是否授权;
• 测试时务必用真机,模拟器默认关闭 overlay 权限且不可开启。
不是“难”,是系统级禁止。iOS 从设计上就不允许第三方 App 创建覆盖其他应用的窗口(UIWindow 级),除非越狱或走企业签名+MDM 配置(面向内部员工设备)。所谓“iOS 悬浮窗插件”,99% 是伪实现:要么是页面内 fixed 元素(受 WebView 限制),要么是锁屏通知卡片(非实时交互),要么依赖后台音频播放等“打擦边球”维持进程活跃——但都不是真正悬浮。
实操建议:
• 别信“iOS 支持悬浮窗”的插件宣传,查源码会发现它只在 Android 分支有 WindowManager 逻辑;
• 如果业务强依赖气泡交互(如客服快捷入口),iOS 端应降级为右上角原生导航栏按钮(pages.json 配置 rightIcon)+ 页面内弹出 diy-popover 组件;
• 所有跨平台方案里,iOS 的“悬浮”永远是妥协结果,这点必须提前和产品对齐。
Ba-FloatWindow 插件图标不显示或模糊怎么办?图标路径、分辨率、基座重编译三者缺一不可。插件读取的是 nativeplugins 目录下编译进原生包的资源,不是 static 或 uni_modules 里的图片,改了文件不重打自定义调试基座=白改。
实操建议:
• 图标文件必须放在 nativeplugins/Ba-FloatWindow/android/res/drawable-xxhdpi/xxx.png,文件名与 JS 中 iconPath: "xxx" 完全一致(不带 .png);
• 提供至少 xxhdpi(48×48 dp → 144×144 px)和 xxxhdpi(192×192 px)两档,否则 iPhone 15 Pro 等高分屏会模糊;
• 每次修改图标后,必须在 HBuilderX 中点击「发行」→「原生App-制作自定义调试基座」,再重新运行,否则无效。