跨端: P5 悬浮玻璃导航取代系统 TabBar —— 自绘浮动条 + 命中区 ≥44vp + 内容让位

(subject 原为「跨端(P5): …」—— 被自己的 commit-hygiene 判据判红:约定是 subject 里带
 `跨端:`,而 `跨端(P5):` 让字面 grep 找不到。判据是对的,改提交不改成判据。)
This commit is contained in:
2026-09-14 15:25:02 +08:00
parent f412751b37
commit 25ac19b343
7 changed files with 373 additions and 29 deletions

View File

@ -0,0 +1,72 @@
/*
* 底部导航(P5:悬浮玻璃条)的**清单与尺寸**。
*
* 为什么数据放在 `.ts` 而不是写在 `MainPage.ets` 里:
* - 判据可以直接 `import` 它(`node --experimental-strip-types` 能跑纯逻辑 `.ts`),
* 于是"命中区 ≥44vp"这类要求判的是**数值本身**,而不是拿正则去源码里猜;
* - 「通信 → 联系人」的顺序与文案是信息架构,和 CommTabs 一样属于跨端要对齐的东西
* (WebUI 侧同样是两项,撤掉会话 tab 的时机见计划文档 §7.15)。
*/
/** 一个底部导航项。字段与 WebUI `Sidebar.tsx` 的项一一对应 */
export interface NavItem {
/** 稳定键(ForEach 的 key,也是判据认的名字) */
key: string;
/** 显示文案(与 WebUI 逐字一致) */
label: string;
/** 图标字形(鸿蒙侧用文本字形,不用猜 sys.media 名字) */
icon: string;
}
/**
* 平级导航项。**只有两项**:通信(内部三栏:收件箱/发件箱/授权)与联系人。
*
* 「会话」原先是个平级 tab,已撤 —— 它不是第三个地方,而是"同一批数据的另一种看法"
* (收件箱按会话折叠、联系人卡片视图就是会话的进度视角)。理由与时机见 `MainPage.build()` 的注释。
* 「日历」等 P6 的内容做完再上入口 —— 不留点进去空着的页签(§7.15)。
*/
export const NAV_ITEMS: NavItem[] = [
{ key: 'comm', label: '通信', icon: '✉️' },
{ key: 'contacts', label: '联系人', icon: '👤' }
];
/** 命中区下限(vp)。**44 是可点区域的下限**,不是"看起来够大"的估计 */
export const NAV_ITEM_MIN_HIT: number = 44;
/** 浮动条自身高度(vp)。≥ NAV_ITEM_MIN_HIT,否则命中区内边距会互相挤压 */
export const NAV_BAR_HEIGHT: number = 56;
/** 悬浮:左右留白(vp)—— 贴边就不是"悬浮"了,WebUI 的底栏同样浮在内容之上 */
export const NAV_BAR_SIDE: number = 16;
/** 悬浮:离屏幕底部的留白(vp) */
export const NAV_BAR_BOTTOM: number = 12;
/** 圆角(vp)。用"胶囊"半径(= 高度一半),与 WebUI 的 `rounded-2xl` 观感一致 */
export const NAV_BAR_RADIUS: number = 28;
/**
* 内容底部要让出的高度(vp):条高 + 离底留白 + 一点余量。
*
* **这是"点得到"的问题,不是美观问题**:条是浮在内容之上的,不让出这段高度,
* 列表最后一行就永远压在玻璃条底下 —— 看得见、点不到。
*/
export const NAV_CONTENT_RESERVE: number = NAV_BAR_HEIGHT + NAV_BAR_BOTTOM + 8;
/** 把任意下标归一化到合法范围(点击/外部传值都过这里,别直接赋值) */
export function normalizeNavIndex(index: number): number {
if (index >= 0 && index < NAV_ITEMS.length) {
return index;
}
return 0;
}
/** 第 index 项的键(内容按它挂载,判据也认它) */
export function navKeyAt(index: number): string {
return NAV_ITEMS[normalizeNavIndex(index)].key;
}
/** 第 index 项的标签(给判据与无障碍文案用) */
export function navLabelAt(index: number): string {
return NAV_ITEMS[normalizeNavIndex(index)].label;
}