跨端: 宽屏右栏空态(splitPlaceholder)—— WebUI 有引导,我们原来一片空白
用户:「你自己看看跟 webui 相比,观感真的差很多」。同 1107vp 视口并排后,
差异确实明显,其中**最扎眼**的一条:宽屏两栏并排时,右栏是**一大片空白**。
WebUI 有引导(`MailView.tsx:121-129`):
信封图标 + 「选择一封邮件查看,或点击左侧「新建」写邮件」
我们什么都没渲染。
★ 第一版放错位置(记下来,这个坑很隐蔽)
我把它写进 `NavDestination` 的 `else` 分支 —— 而 **`NavDestination` 只在
push 之后才挂载**,栈空时它根本不存在 ⇒ 那个 else **一次都不会显示**
(实测:加上去之后右栏仍然全空)。
正确入口是 `splitPlaceholder(ComponentContent)`:系统给"右栏默认页"的专用 API
(`navigation.d.ts`,API 20+,我们是 23),由 `Navigation` 在栈空时自己渲染。
★ 三个 ArkTS 约束(都撞了才过)
① `splitPlaceholder` 要的 `wrapBuilder` 只接受**全局** `@Builder` 函数 ——
写成 struct 成员方法会报 "The wrapBuilder's parameter should be '@Builder' function"。
内容本身是静态的(不需要 `this`),所以全局正好。
② `wrapBuilder` 是**全局声明**(`common.d.ts:27448`),**不在** `@kit.ArkUI` 里 ——
从 kit 引会报 "has no exported member"。
③ `ComponentContent` 要从 `@kit.ArkUI` 引。
文案**逐字对齐 WebUI**(同一句话,不自己改写)—— 与本仓既有纪律一致
(`harmony-logic` 里「空态主句与 WebUI 逐字一致」那条是同源要求)。
设备验证:`选择一封邮件查看,或点击左侧「新建」写邮件` 已在右栏渲染(布局树可见)。
This commit is contained in:
@ -76,7 +76,7 @@ import { PushService, PushRoute } from '../api/PushService';
|
||||
*/
|
||||
import { CalendarPage } from './CalendarPage';
|
||||
import { SettingsPane } from './SettingsPage';
|
||||
import { LengthMetrics } from '@kit.ArkUI';
|
||||
import { LengthMetrics, ComponentContent } from '@kit.ArkUI';
|
||||
import { Insets, KEY_WINDOW_INSETS } from '../model/WindowInsets';
|
||||
import {
|
||||
LIST_FADE_LENGTH,
|
||||
@ -117,6 +117,42 @@ function compactMailTime(iso: string): string {
|
||||
* Navigation 目标页:按官方示例在 NavDestination.onReady 读取路径参数。
|
||||
* 系统 Navigation 自动决定 Stack / Split;这里不读窗口宽度、不手搓分栏。
|
||||
*/
|
||||
/**
|
||||
* 右栏占位(`Navigation` **split 模式**下、栈空时显示的那一块)。
|
||||
*
|
||||
* ★★ 2026-09-20 补(用户:「你自己看看跟 webui 相比,观感真的差很多」)。
|
||||
*
|
||||
* 宽屏下详情是**常驻右栏**;没选邮件时 WebUI 有引导(`MailView.tsx:121-129`):
|
||||
* 信封图标 + 「选择一封邮件查看,或点击左侧「新建」写邮件」
|
||||
* 而我们什么都不渲染 ⇒ 两栏并排时右栏是**一大片空白**
|
||||
* (实测同 1107vp 视口并排:WebUI 那栏中央有图标+文案,我们那栏全空)。
|
||||
*
|
||||
* ★ 为什么用 `splitPlaceholder` 而不是"在 `NavDestination` 里加 `else` 分支":
|
||||
* `NavDestination` **只在 push 之后才挂载**,栈空时它根本不存在 ——
|
||||
* 我第一版就是写在它的 `else` 里,**一次都不会显示**(已撤销)。
|
||||
* `splitPlaceholder(ComponentContent)` 是系统给"右栏默认页"的专用入口
|
||||
* (`navigation.d.ts`,API 20+,我们是 23),由 `Navigation` 在栈空时自己渲染。
|
||||
*
|
||||
* ★ 必须是**全局** `@Builder`:`splitPlaceholder` 要的是
|
||||
* `wrapBuilder<[]>(fn)`,而它只接受全局 @Builder 函数
|
||||
* (成员方法会报 "The wrapBuilder's parameter should be '@Builder' function")。
|
||||
* 内容本身是静态的,不需要 `this`,所以全局正好。
|
||||
*
|
||||
* 文案**逐字对齐 WebUI**(同一句话,不自己改写)—— 本仓纪律:
|
||||
* 两端对同一件事说同一句话(见 `harmony-logic` 里「空态主句逐字一致」那条)。
|
||||
*/
|
||||
@Builder
|
||||
function DetailPlaceholder() {
|
||||
Column() {
|
||||
AmIcon({ iconName: 'mail', iconSize: 40, iconColor: Theme.textSubtleFor() })
|
||||
Text('选择一封邮件查看,或点击左侧「新建」写邮件')
|
||||
.fontSize(14).fontColor(Theme.textMuted)
|
||||
.margin({ top: 12 })
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}
|
||||
|
||||
@Component
|
||||
struct MailDetailDestination {
|
||||
@State mailId: string = '';
|
||||
@ -1443,6 +1479,25 @@ struct CommPage {
|
||||
this.navPathStack.pushPath({ name: MAIL_DETAIL_ROUTE, param: params });
|
||||
}
|
||||
|
||||
/**
|
||||
* 右栏占位(`Navigation` **split 模式**下、栈空时显示的那一块)。
|
||||
*
|
||||
* ★★ 2026-09-20 补(用户:「你自己看看跟 webui 相比,观感真的差很多」)。
|
||||
*
|
||||
* 宽屏下详情是**常驻右栏**;没选邮件时 WebUI 有引导(`MailView.tsx:121-129`):
|
||||
* 信封图标 + 「选择一封邮件查看,或点击左侧「新建」写邮件」
|
||||
* 而我们什么都不渲染 ⇒ 两栏并排时右栏是**一大片空白**
|
||||
* (实测同 1107vp 视口并排:WebUI 那栏中央有图标+文案,我们那栏全空)。
|
||||
*
|
||||
* ★ 为什么用 `splitPlaceholder` 而不是"在 `NavDestination` 里加 `else` 分支":
|
||||
* `NavDestination` **只在 push 之后才挂载**,栈空时它根本不存在 ——
|
||||
* 我第一版就是写在它的 `else` 里,**一次都不会显示**(已撤销)。
|
||||
* `splitPlaceholder(ComponentContent)` 是系统给"右栏默认页"的专用入口
|
||||
* (`navigation.d.ts`,API 20+,我们是 23),由 `Navigation` 在栈空时自己渲染。
|
||||
*
|
||||
* 文案**逐字对齐 WebUI**(同一句话,不自己改写)—— 本仓纪律:
|
||||
* 两端对同一件事说同一句话(见 `harmony-logic` 里「空态主句逐字一致」那条)。
|
||||
*/
|
||||
@Builder
|
||||
DestinationBuilder(name: string, param: Object) {
|
||||
if (name === MAIL_DETAIL_ROUTE) {
|
||||
@ -1575,6 +1630,10 @@ struct CommPage {
|
||||
.minContentWidth(360)
|
||||
.hideTitleBar(true)
|
||||
.width('100%').height('100%')
|
||||
/* 右栏占位:栈空时显示引导(否则宽屏两栏并排时右栏是一大片空白)。
|
||||
用系统入口 `splitPlaceholder`,**不是** NavDestination 的 else —— 后者栈空时不挂载。 */
|
||||
.splitPlaceholder(new ComponentContent(
|
||||
this.getUIContext(), wrapBuilder<[]>(DetailPlaceholder)))
|
||||
/*
|
||||
* ★★ 2026-09-19 修(用户:「你这玻璃也不透明啊」)。
|
||||
*
|
||||
@ -1787,27 +1846,6 @@ struct ContactsTab {
|
||||
DestinationBuilder(name: string, param: Object) {
|
||||
if (name === MAIL_DETAIL_ROUTE) {
|
||||
MailDetailDestination({ navReserve: this.navReserve, bgActive: this.bgActive })
|
||||
} else {
|
||||
/*
|
||||
* ★★ 2026-09-20 补(用户:「你自己看看跟 webui 相比,观感真的差很多」)。
|
||||
*
|
||||
* 宽屏下详情是**常驻右栏**,没选邮件时这一栏该有**空态引导**。
|
||||
* WebUI 有(`MailView.tsx:121-129`):
|
||||
* 信封图标 + 「选择一封邮件查看,或点击左侧「新建」写邮件」
|
||||
* 而我们这边什么都不渲染 ⇒ **一大片纯白/壁纸**,两栏并排时尤其空。
|
||||
* 实测(同 1107vp 视口并排):WebUI 右栏中央有图标+文案,我们那栏全空。
|
||||
*
|
||||
* 文案**逐字对齐 WebUI**(同一句话,不自己改写)—— 本仓纪律:
|
||||
* 两端对同一件事说同一句话(`harmony-logic` 里那条「空态主句逐字一致」同源)。
|
||||
*/
|
||||
Column() {
|
||||
AmIcon({ iconName: 'mail', iconSize: 40, iconColor: Theme.textSubtleFor() })
|
||||
Text('选择一封邮件查看,或点击左侧「新建」写邮件')
|
||||
.fontSize(14).fontColor(Theme.textMuted)
|
||||
.margin({ top: 12 })
|
||||
}
|
||||
.width('100%').height('100%')
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1975,6 +2013,10 @@ struct ContactsTab {
|
||||
.minContentWidth(360)
|
||||
.hideTitleBar(true)
|
||||
.width('100%').height('100%')
|
||||
/* 右栏占位:栈空时显示引导(否则宽屏两栏并排时右栏是一大片空白)。
|
||||
用系统入口 `splitPlaceholder`,**不是** NavDestination 的 else —— 后者栈空时不挂载。 */
|
||||
.splitPlaceholder(new ComponentContent(
|
||||
this.getUIContext(), wrapBuilder<[]>(DetailPlaceholder)))
|
||||
/* 同 CommPage 的 Navigation:不设背景时系统默认不透明白,会把里面
|
||||
已经透明的窗格盖住。联系人页是同一形状,同一修法。 */
|
||||
.attributeModifier(PaneModifier.of(this.bgActive))
|
||||
|
||||
Reference in New Issue
Block a user