Files
LanMountainDesktop/.trae/documents/skeleton-screen-plan.md
2026-04-15 10:49:04 +08:00

118 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 骨架页Skeleton Screen实施计划
## 问题分析
当前首次启动时,用户看到的现象:
1. 全屏窗口立即显示,但状态栏组件全部 `IsVisible="False"`(空白)
2. 头像区域只有 fallback 文字 "U",尺寸未计算(显得巨大)
3. 底部 Dock 任务栏已经渲染但内容为空
4. 壁纸加载完成前,桌面区域是透明/黑色的
5. 整体看起来就是一个"Dock 栏覆盖全屏 + 巨大头像"的半成品状态
**根本原因**`OnOpened` 中有大量同步初始化操作壁纸解码、组件布局、启动器扫描等在它们完成之前UI 元素要么不可见要么处于默认状态。
## 方案概述
`DesktopPage` 层添加一个**骨架遮罩层**,覆盖在真实内容之上,在初始化完成前显示骨架占位,初始化完成后淡出消失。
### 骨架页布局
```
┌──────────────────────────────────────────────────────────────┐
│ [状态栏骨架] │
│ ┌─────────┐ ┌──────────────────┐ ┌─────────┐ │
│ │ ○ 头像 │ │ ████ 时钟 ████ │ │ ○ ○ │ │
│ └─────────┘ └──────────────────┘ └─────────┘ │
│ │
│ (桌面区域 - 壁纸层) │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ [Dock 任务栏骨架] │ │
│ │ ██ ████████ ████████ ████████ ████████ ○ │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
### 骨架元素
| 区域 | 骨架元素 | 形状 | 说明 |
| ------- | ------ | ----------------------------------- | ----------------------------- |
| 状态栏-中间 | 时钟骨架 | 圆角矩形(`DesignCornerRadiusComponent` | 模拟 ClockWidget 的胶囊形状 |
| 状态栏-中间 | 文本胶囊骨架 | 圆角矩形(较小) | 模拟 TextCapsuleWidget |
| 底部 Dock | 头像骨架 | 圆形 | 模拟 TaskbarProfileAvatarBorder |
| 底部 Dock | 操作按钮骨架 | 圆角矩形 | 模拟任务栏按钮 |
| 底部 Dock | 分隔线骨架 | 细长矩形 | 模拟按钮间分隔 |
### 骨架样式
* **颜色**:使用 `AdaptiveGlassPanelBackgroundBrush` 作为基础色,叠加一个 **Shimmer 动画**(微光扫过效果)
* **圆角**:与真实组件一致,使用 `DesignCornerRadiusComponent`
* **动画**Shimmer 微光从左到右扫过,周期 2s使用 `FluttermotionToken` 缓动
## 实施步骤
### Step 1: 创建 Shimmer 动画画刷
`GlassModule.axaml` 或新建 `SkeletonStyles.axaml` 中定义:
* 创建 `ShimmerBrush`:一个 `LinearGradientBrush`,包含高光条带
* 创建 `ShimmerAnimation` storyboard让高光条带从左到右移动
* 定义 `skeleton-shimmer` 样式类:应用 ShimmerBrush + 动画
### Step 2: 在 MainWindow\.axaml 中添加骨架遮罩层
`DesktopPage` Grid 内、所有真实内容之上添加一个 `Grid x:Name="SkeletonOverlay"`
* 初始 `IsVisible="True"``ZIndex="999"`
* 包含状态栏骨架区域和底部 Dock 骨架区域
* 使用与真实布局相同的 Grid RowDefinitions确保骨架元素对齐
### Step 3: 在 MainWindow\.axaml.cs 中控制骨架显示/隐藏
*`OnOpened` 开始时,骨架层可见
*`OnOpened` 末尾(所有初始化完成后),调用 `HideSkeletonOverlayAsync()`
* `HideSkeletonOverlayAsync()`:播放淡出动画 → 设置 `IsVisible="False"`
* 如果启用了滑入滑出过渡,骨架层在入场动画期间也应可见,入场动画完成后再淡出
### Step 4: 骨架元素尺寸适配
* 骨架元素需要在 `ApplyTaskbarSettings()` 后更新尺寸(因为 `taskbarCellHeight` 等值在 OnOpened 中才计算)
* 或者在 XAML 中使用相对尺寸(百分比/比例),避免依赖代码计算
### Step 5: 与窗口过渡动画的协调
* 入场动画(`PrepareEnterAnimation` / `PlayEnterAnimation`)期间,骨架层应保持可见
* 入场动画完成后,先短暂显示骨架(\~100ms然后淡出骨架
* 退场动画时,无需特殊处理(骨架已隐藏)
## 涉及文件
| 文件 | 改动类型 |
| --------------------------------- | -------------------- |
| `Styles/SkeletonStyles.axaml`(新建) | Shimmer 画刷 + 骨架样式类 |
| `Views/MainWindow.axaml` | 添加 SkeletonOverlay 层 |
| `Views/MainWindow.axaml.cs` | 骨架显示/隐藏逻辑 |
| `App.axaml` | 引入 SkeletonStyles 资源 |
## 不涉及的文件
* 不修改组件代码ClockWidget、TextCapsuleWidget 等)
* 不修改设置系统
* 不修改 App.axaml.cs 的启动流程