更新记录
1.0.2(2026-08-19)
更新文档描述
1.0.1(2026-08-19)
- 修复:vue / nvue tab 页混用时,切换 tab 会偶发把 tabBar 误隐藏。
- 文档:补全 readme 中
setupGlassTabBar全部参数(含 midButton 各字段)的示例与说明
平台兼容性
uni-app(4.66)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | × | × | × | √ | √ | × | 13 | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
glass-tabbar 液态玻璃 tabBar
基于 UTS 的 iOS 26 Liquid Glass(液态玻璃) 底部 tabBar 插件。
- ✅ iOS 26+:系统级
UITabBar+ Liquid Glass,支持中间凸起按钮 - ✅ iOS < 26 / Android:自动降级,继续使用
pages.json原生 tabBar - ✅ 兼容 vue 与 nvue(可混用,例如首页 nvue、其余 tab 页 vue)
- ✅ 附带 JS 业务封装,开箱接入
switchTab/ 二级页隐藏 - ✅ 安全区增强为可选功能(
setGlassSafeArea),默认不强制处理 - ✅ tabBar 挂载在独立高层级浮层窗口上,跨页面切换不闪烁、不被遮挡
本插件为 App 端 UTS 原生能力。调试请使用包含本插件的自定义调试基座;Mac 真机可走 Xcode 本地编译。
一、目录说明
uni_modules/glass-tabbar
├── package.json
├── readme.md
├── changelog.md
├── license.md
├── js_sdk/
│ └── index.js # 业务封装(推荐使用)
└── utssdk/
├── interface.uts # API 声明
├── app-ios/ # iOS 原生实现
└── app-android/ # Android 空实现(降级)
二、快速开始(推荐 js_sdk)
1. 保持 pages.json 原生 tabBar
插件不会替换你的 pages.json 配置。低版本系统仍依赖原生 tabBar;iOS 26 会在运行时 hideTabBar 并绘制玻璃 tabBar。
2. 首个 tab 页初始化(完整参数示例)
下面示例用到了 setupGlassTabBar 支持的全部参数,实际接入按需精简即可(大多数字段都是可选的)。
import {
setupGlassTabBar,
handleGlassTabPageShow,
handleGlassTabPageHide
} from '@/uni_modules/glass-tabbar/js_sdk/index.js'
export default {
onShow() {
setupGlassTabBar({
// 初始选中索引,默认 0
current: 0,
// 未选中 / 选中颜色(十六进制),默认 #7A7E83 / #007AFF
color: '#7A7E83',
selectedColor: '#007AFF',
// 是否启用左右滑动切 tab,默认 true;
// 用系统 UITabBar 自身的选择动画时建议关闭,避免和自定义手势冲突
enableSwipe: false,
// tab 列表,顺序必须与 pages.json 的 tabBar.list 保持一致
list: [
{
text: '首页',
// icon / activeIcon:iOS SF Symbol 名称;不传 activeIcon 则选中态复用 icon,仅切换颜色
icon: 'house',
activeIcon: 'house.fill',
pagePath: 'pages/home/index'
},
{
text: '发现',
// iconPath / selectedIconPath:本地图片,优先级高于 icon;
// 建议原图约 25×25pt(@2x 50px / @3x 75px),插件会自动按比例缩放到标准 tab 尺寸;
// 不传 selectedIconPath 则复用 iconPath,仅切换为 selectedColor
iconPath: 'static/image/discover.png',
selectedIconPath: 'static/image/discover_sel.png',
pagePath: 'pages/discover/index'
},
{
text: '消息',
icon: 'message',
activeIcon: 'message.fill',
pagePath: 'pages/message/index'
},
{
text: '我的',
icon: 'person',
activeIcon: 'person.fill',
pagePath: 'pages/my/index'
}
],
// 中间凸起按钮,完全可选;不需要则整个 midButton 都不传
midButton: {
text: '发布', // 文案;showText=false 时不显示
icon: 'plus', // SF Symbol,默认 "plus"
iconPath: '', // 本地图片;传入后优先于 icon,且保留原始颜色不受 selectedColor 影响
isRaised: false, // 是否凸出 tabBar,默认 true
showText: false // 是否显示文案,默认 true
},
// 点击任意 tab 时的额外回调(内部已自动执行 uni.switchTab,这里通常做统计等附加逻辑)
onChange(index) {
console.log('切换到 tab', index)
},
// 中间凸起按钮点击回调(不参与 list 索引,不改变选中态)
onMidButtonTap() {
uni.showToast({ title: '点击了发布', icon: 'none' })
}
})
// 建议每个 tab 页 onShow 都调用一次,保证从其它 tab / 二级页返回时正确显示与同步选中
handleGlassTabPageShow(0)
},
onHide() {
handleGlassTabPageHide()
}
}
3. 其他 tab 页
import {
handleGlassTabPageShow,
handleGlassTabPageHide
} from '@/uni_modules/glass-tabbar/js_sdk/index.js'
export default {
onShow() {
// 参数为该页在 list 中的索引(从 0 开始)1代表第二个tab页面
handleGlassTabPageShow(1)
},
onHide() {
handleGlassTabPageHide()
}
}
handleGlassTabPageShow/handleGlassTabPageHide内部通过原生单例的“世代计数器”判断是否真的离开了 tab 区(详见下方常见问题第 4 条),vue 与 nvue 页面混用完全没有影响,每个 tab 页照抄这段即可。
三、可选功能:安全区设置
安全区相关能力不是必须的。只有在浮动玻璃 tabBar 下方出现露白时,再按需开启。
setGlassSafeArea(options)
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
| fillColor | string | '' |
Home Indicator 区域补色;不传/空字符串表示不铺色 |
示例 1:底部补色
import { setGlassSafeArea } from '@/uni_modules/glass-tabbar/js_sdk/index.js'
// 建议取当前页背景渐变末端色;切换 tab 时可再次调用更新颜色
setGlassSafeArea({
fillColor: '#38ef7d'
})
示例 2:按 tab 页切换补色
export default {
onShow() {
handleGlassTabPageShow(2)
setGlassSafeArea({ fillColor: '#38ef7d' })
}
}
说明:该功能仅在 iOS 26 液态玻璃模式生效;不会改写
manifest.json全局safearea,不影响低版本 iOS。
四、js_sdk API
| 方法 | 说明 |
|---|---|
setupGlassTabBar(config) |
初始化玻璃 tabBar(建议在首个 tab 页 onShow),返回是否成功启用液态玻璃 |
handleGlassTabPageShow(index) |
tab 页 onShow 时调用:显示 tabBar 并同步选中态 |
handleGlassTabPageHide() |
tab 页 onHide 时调用:仅在真正离开 tab 区(进入二级页)时才隐藏 tabBar |
setGlassSafeArea({ fillColor }) |
可选:设置底部安全区补色 |
getGlassSafeAreaConfig() |
读取当前安全区配置 |
shouldUseLiquidGlass() |
当前是否 iOS 26+(是否会启用液态玻璃) |
updateGlassTabBarActive(index) |
手动同步高亮,不触发 onChange |
syncGlassTabBar(route) |
按路由字符串同步显示/隐藏(非 tab 页会自动隐藏) |
getTabIndex(route) |
路由转 tab 索引,非 tab 页返回 -1 |
removeGlassTabBar() |
销毁玻璃 tabBar(一般不需要主动调用) |
setupGlassTabBar(config) 参数详情
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
list |
Array | - | 必填,tab 列表,顺序需与 pages.json 的 tabBar.list 一致 |
list[].text |
string | - | 文案 |
list[].icon |
string | - | 未选中态图标,iOS SF Symbol 名称,如 "house" |
list[].activeIcon |
string | 复用 icon |
选中态图标(SF Symbol);不传则复用 icon,仅切换颜色 |
list[].iconPath |
string | - | 未选中态本地图片路径;优先级高于 icon;建议原图约 25×25pt |
list[].selectedIconPath |
string | 复用 iconPath |
选中态本地图片路径;不传则复用 iconPath,仅切换为 selectedColor |
list[].pagePath |
string | - | 对应 tab 页路径,用于点击后 uni.switchTab |
current |
number | 0 |
初始选中索引 |
color |
string | #7A7E83 |
未选中文字/图标颜色(十六进制) |
selectedColor |
string | #007AFF |
选中文字/图标颜色(十六进制) |
enableSwipe |
boolean | true |
是否启用左右滑动切 tab |
midButton |
Object | - | 中间凸起按钮,完全可选 |
midButton.text |
string | - | 按钮文案;showText=false 时不显示 |
midButton.icon |
string | "plus" |
SF Symbol 名称 |
midButton.iconPath |
string | - | 本地图片路径;传入后优先于 icon,且保留原始颜色 |
midButton.isRaised |
boolean | true |
是否凸出 tabBar;false 时按钮完整显示在 tabBar 内 |
midButton.showText |
boolean | true |
是否显示文案;false 时只显示图标 |
onChange |
Function(index) | - | 点击任意 tab 的额外回调(内部已自动 uni.switchTab) |
onMidButtonTap |
Function | - | 中间按钮点击回调 |
五、原生 UTS API(高级)
也可直接调用原生能力,一般业务侧优先使用 js_sdk,无需直接操作以下 API:
import {
showGlassTabBar,
hideGlassTabBar,
setGlassTabBarActive,
setGlassTabBarHidden,
extendGlassTabPageToBottom,
setGlassSafeAreaFillColor,
restoreGlassTabPageSafeArea
} from '@/uni_modules/glass-tabbar'
| 方法 | 说明 |
|---|---|
showGlassTabBar(options) |
创建并显示玻璃 tabBar(对应 setupGlassTabBar 首次调用) |
hideGlassTabBar() |
销毁玻璃 tabBar 及浮层窗口 |
setGlassTabBarActive(index) |
同步选中项,不触发 onChange |
setGlassTabBarHidden(hidden) |
仅切换可见性,不销毁视图 |
extendGlassTabPageToBottom() |
将当前页铺满屏幕底部(配合安全区增强使用) |
setGlassSafeAreaFillColor(color) |
更新底部安全区补色 |
restoreGlassTabPageSafeArea() |
恢复系统底部安全区 |
六、调试与打包注意
- 必须使用包含本插件的自定义调试基座(或 Mac 真机 + Xcode 本地编译 UTS)
- 修改
.uts后请完整重新运行,热刷新不会重新注入原生类 - 模拟器若报
undefined class: UTSSDKModulesGlassTabbarIndexSwift,说明当前基座未打入本插件 - 正式云打包时勾选本 UTS 插件即可
七、常见问题
1. 底部 Home Indicator 露白?
这是可选能力。需要时调用:
setGlassSafeArea({ fillColor: '#你的页面底色' })
不要为了本插件去改全局 manifest.safearea(否则会影响所有 iOS 版本)。
2. Android / 低版本 iOS 会怎样?
setupGlassTabBar 返回 false,页面继续走 pages.json 原生 tabBar,无额外影响。
3. vue / nvue 都能用吗?可以混用吗?
可以。玻璃 tabBar 挂在独立的原生浮层窗口上,与页面渲染方式(vue webview / nvue 原生视图)无关,同一个项目里 tab 页可以随意混用 vue 和 nvue。
4. 为什么切换 tab 时 tabBar 不会再被误隐藏?
handleGlassTabPageHide 只在“确实离开 tab 区(比如进入二级页)”时才隐藏 tabBar;纯粹在 tab 之间切换不应该触发隐藏。这个判断依赖一个“世代计数器”:
- 每次任意 tab 页“显示/激活” tabBar,世代号 +1;
onHide时先记录当时的世代号,延时一小段时间后再检查世代号是否变化,变化了说明期间已经有新 tab 页显示,放弃隐藏。
这个计数器存放在原生单例里,而不是 JS 侧的模块变量——因为 vue 的每个 tab 页(每个 webview)运行在各自独立的 JS 上下文中,同一份 .js 文件在不同页面里会各自加载一份实例,JS 侧的模块变量并不会在页面之间共享。放在原生单例(整个 App 进程内唯一)里才能保证跨 vue / nvue 页面正确生效。业务侧无需关心这个细节,照抄第二、三节的示例即可。
5. 浮层窗口会不会挡住页面中间的点击(比如跳转二级页面的按钮)?
不会。玻璃 tabBar 挂载的浮层窗口只覆盖 tabBar(含中间凸起按钮)所在的底部条状区域,不会铺满全屏,因此页面中间、顶部区域的点击不会经过这个浮层窗口,天然不受影响。
八、隐私与权限
- 无广告
- 不收集、上传用户数据
- 无需系统权限

收藏人数:
购买普通授权版(
试用
赞赏(0)
下载 43
赞赏 0
下载 12518864
赞赏 1943
赞赏
京公网安备:11010802035340号