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

5.9 KiB
Raw Blame History

骨架页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 的启动流程