fix(harmony): 图标按 px→vp 正确缩放 + 底栏四入口 + 卡片 10vp 缩进
图标过小的根因(实图硬证):`Path.commands` 的坐标按 **px** 解释,不是 vp。
- `Shape.viewPort` 只裁剪不缩放(官方样例"缩放成立"是因为它用 Rect/Circle
自带 vp 宽高,不是裸 Path.commands);
- 改动前的 `Path.scale({iconSize/24})` 对 iconSize=24 等于 1.0,同样没缩放。
症状:FAB 内 compose 只画 24px(应 24vp=84px),且偏在盒子左上角。
修法:`scale({vp2px(iconSize)/24})` 把 24 单位路径放大到 iconSize vp;
`scale` 会连带放大描边,故 `strokeWidth = strokeWeight / vp2px(1)` 抵消,
否则 1.8vp 描边会变成 ~7.3vp 的"实心块"(实图已验证)。
用 `this.getUIContext().vp2px()` 而非全局 `vp2px`——后者已废弃,
`harmony-system-api` 判据对全局调用默认判红。
验收(模拟器实图,密度 3.489):
- FAB 内 compose 图标 84px = 24vp ✓(原 24px)
- 底栏图标描边 7-8px ≈ 1.8/24×28vp=7.3px ✓(原为实心块)
- 四个图标均为清晰描边,与 WebUI icons.tsx 同几何
底栏四入口:新增"我的"(person → pages/SettingsPage),对齐 WebUI
通信/日历/联系人/我的;NAV_CONTENT_ITEMS 保持宽屏侧栏三项,
避免宽屏出现重复 person 图标。
卡片缩进:`width('100%') + margin({left:10,right:10})` 在 ArkUI 里不会
缩到 90%——margin 加在宽度外面,卡片顶出父容器(实测左缘只留 ~1px,
列表卡才有正确 10vp)。改为外层容器加 padding。验收:页头卡与邮件卡
左缘同为 x=35(10.0vp)、右缘 x=1219。
推送:reportToken 先申请通知权限再取 token(部分设备权限未开时
getToken 返回空 / 报 1600004),并补两条文件形状判据钉住
client_id 配置与调用顺序。
测试:198 passed / 0 failed。
This commit is contained in:
@ -19,19 +19,34 @@ export interface NavItem {
|
||||
*
|
||||
* 2026-09-15 之前这里是 emoji 字形(`✉️`/`📅`/`👤`),理由是"不用猜 sys.media 名字"。
|
||||
* 那条理由只解释了"为什么不用系统资源名",却把 emoji 当成了唯一替代 —— 结果是:
|
||||
* · WebUI 在 `icons.tsx` 第一行就写着「**纯 SVG 图标,全站不使用 emoji**」,
|
||||
* · WebUI 在 `icons.tsx` 第一行就写着「**纯 SVG 图标,全站不使用 emoji**」,
|
||||
* 两边**同一个产品却两套图标语言**;
|
||||
* · emoji 由系统字体渲染,颜色不受 `fontColor` 控制、随厂商与版本变形,
|
||||
* · emoji 由系统字体渲染,颜色不受 `fontColor` 控制、随厂商与版本变形,
|
||||
* 选中/未选中只能靠整体透明度示意,做不到 WebUI 那种"线性描边图标 + 品牌色"。
|
||||
*
|
||||
* 现在改用 ArkUI 原生 `Path`(`common/Icons.ets`,由 WebUI 的 TSX 自动生成),
|
||||
* 既不需要猜 `sys.media` 名字,又能吃主题色(深色模式一处也不漏)。
|
||||
*/
|
||||
iconKey: string;
|
||||
/**
|
||||
* 外壳入口:点击后路由到独立 @Entry 页(`pages/xxx`),不在主界面挂内容。
|
||||
* 留空 = 内容窗格(由 `MainPage` 的 currentIndex 分派挂内容)。
|
||||
*
|
||||
* 为什么单列这个字段而不是把「我的」塞进 currentIndex 分派:设置页是 **@Entry**
|
||||
* (自带返回按钮、独立路由栈),不能当作可嵌入的 pane —— 在内容分派里给它
|
||||
* 占一个 index 会出现"点了没内容、或每次重建都 pushUrl"的尴尬。外壳入口在
|
||||
* NavItem 的 onClick 里直接路由,与 WideSidebar 底部那个设置按钮是同一行为。
|
||||
*/
|
||||
route?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平级导航项。**三项**:通信(内部三栏:收件箱/发件箱/授权)、日历、联系人。
|
||||
* 底栏四枚图标 = 三个内容窗格 + 一个外壳入口,与 WebUI `NarrowNav.tsx` 的四入口一一对应。
|
||||
*
|
||||
* 前**三项**是平级内容窗格:通信(内部三栏:收件箱/发件箱/授权)、日历、联系人。
|
||||
* 第**四项**「我的」是外壳入口(`route` 指向 `pages/SettingsPage`)—— 它承载
|
||||
* 设置/主题/壁纸/账号,是独立 @Entry 页,不在主界面 currentIndex 分派里挂内容
|
||||
* (理由见 `NavItem.route` 的注释;WideSidebar 同样把设置单列在导航项之后)。
|
||||
*
|
||||
* 「会话」原先是个平级 tab,已撤 —— 它不是第三个地方,而是"同一批数据的另一种看法"
|
||||
* (收件箱按会话折叠、联系人卡片视图就是会话的进度视角)。理由见 `MainPage.build()` 的注释。
|
||||
@ -44,7 +59,8 @@ export interface NavItem {
|
||||
export const NAV_ITEMS: NavItem[] = [
|
||||
{ key: 'comm', label: '通信', iconKey: 'inbox' },
|
||||
{ key: 'calendar', label: '日历', iconKey: 'calendar' },
|
||||
{ key: 'contacts', label: '联系人', iconKey: 'contacts' }
|
||||
{ key: 'contacts', label: '联系人', iconKey: 'contacts' },
|
||||
{ key: 'me', label: '我的', iconKey: 'person', route: 'pages/SettingsPage' }
|
||||
];
|
||||
|
||||
/** 命中区下限(vp)。**44 是可点区域的下限**,不是"看起来够大"的估计 */
|
||||
@ -84,20 +100,31 @@ export const NAV_CONTENT_GAP: number = 8;
|
||||
*/
|
||||
export const NAV_CONTENT_RESERVE: number = NAV_BAR_HEIGHT + NAV_BAR_BOTTOM + NAV_CONTENT_GAP;
|
||||
|
||||
/** 把任意下标归一化到合法范围(点击/外部传值都过这里,别直接赋值) */
|
||||
/** 内容窗格的数量(前三项:通信/日历/联系人)—— `MainPage` 的 currentIndex 分派按它穷尽,
|
||||
* `NAV_CONTENT_ITEMS` 也按它切片 */
|
||||
export const NAV_CONTENT_COUNT: number = 3;
|
||||
|
||||
/** 内容窗格的清单(前三项:通信/日历/联系人)—— 宽屏侧栏与 currentIndex 分派都用它
|
||||
* (第 4 项「我的」是外壳入口,不在内 —— 否则宽屏侧栏会出现两个 person 图标) */
|
||||
export const NAV_CONTENT_ITEMS: NavItem[] = NAV_ITEMS.slice(0, NAV_CONTENT_COUNT);
|
||||
|
||||
/** 外壳入口(第 4 项「我的」)的路由目标 —— 与 WideSidebar 的 onSettings 同一地址 */
|
||||
export const NAV_SETTINGS_ROUTE: string = 'pages/SettingsPage';
|
||||
|
||||
/** 把任意下标归一化到内容窗格的合法范围(点击/外部传值都过这里,别直接赋值) */
|
||||
export function normalizeNavIndex(index: number): number {
|
||||
if (index >= 0 && index < NAV_ITEMS.length) {
|
||||
if (index >= 0 && index < NAV_CONTENT_COUNT) {
|
||||
return index;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** 第 index 项的键(内容按它挂载,判据也认它) */
|
||||
/** 第 index 项的键(内容按它挂载,判据也认它) —— 越界回 0(内容窗格,不含外壳入口) */
|
||||
export function navKeyAt(index: number): string {
|
||||
return NAV_ITEMS[normalizeNavIndex(index)].key;
|
||||
return NAV_CONTENT_ITEMS[normalizeNavIndex(index)].key;
|
||||
}
|
||||
|
||||
/** 第 index 项的标签(给判据与无障碍文案用) */
|
||||
/** 第 index 项的标签(给判据与无障碍文案用) —— 越界回 0(内容窗格,不含外壳入口) */
|
||||
export function navLabelAt(index: number): string {
|
||||
return NAV_ITEMS[normalizeNavIndex(index)].label;
|
||||
return NAV_CONTENT_ITEMS[normalizeNavIndex(index)].label;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user