Files
LanMountainDesktop/docs/03-组件设计规范/03-布局规范.md

18 KiB
Raw Blame History

布局规范

本文档详细说明组件布局规范,包括安全区域、间距系统、网格系统和响应式布局。

🎯 布局目标

良好的布局应该:

  • 内容不会被截断或溢出
  • 视觉元素对齐整齐
  • 留白充足,不拥挤
  • 适配不同的组件尺寸
  • 易于维护和扩展

📐 安全区域Safe Area

什么是安全区域?

安全区域是组件内容必须保持的最小边距,确保内容不会紧贴组件边缘,保持视觉舒适度。

┌─────────────────────────────────────────┐
│ ◄─────── 16px 安全边距 ───────►         │
│ ▲                                       │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │                                 │ │ │
│ │ │     这是内容安全区域            │ │ │
│ │ │     所有内容都应该在这里        │ │ │
│ 16px│     不要紧贴边缘                │ │ │
│ │ │                                 │ │ │
│ │ └─────────────────────────────────┘ │ │
│ ▼                                       │
│         ◄─────── 16px 安全边距 ───────► │
└─────────────────────────────────────────┘

安全区域标准

位置 最小边距 推荐边距 说明
上边距 16px 16-20px 顶部内容到边缘
下边距 16px 16-20px 底部内容到边缘
左边距 16px 16-24px 左侧内容到边缘
右边距 16px 16-24px 右侧内容到边缘

AXAML 实现

<!-- ✅ 正确:使用 Padding 创建安全区域 -->
<Border Background="{DynamicResource CardBackgroundBrush}"
        CornerRadius="8"
        Padding="16">
  <!-- 内容区域 -->
  <StackPanel Spacing="8">
    <TextBlock Text="标题" FontSize="16"/>
    <TextBlock Text="内容" FontSize="14"/>
  </StackPanel>
</Border>

<!-- ✅ 使用设计资源 -->
<Border Background="{DynamicResource CardBackgroundBrush}"
        CornerRadius="{DynamicResource DesignCornerRadiusComponent}"
        Padding="{DynamicResource DesignPaddingComponent}">
  <!-- 内容 -->
</Border>

<!-- ❌ 错误:没有安全边距 -->
<Border Background="{DynamicResource CardBackgroundBrush}"
        CornerRadius="8">
  <!-- 内容会紧贴边缘,不美观 -->
  <TextBlock Text="标题"/>
</Border>

不同 Padding 配置

<!-- 统一边距 -->
<Border Padding="16">...</Border>

<!-- 左右、上下不同 -->
<Border Padding="16,12">...</Border>
<!-- 等价于: Left=Right=16, Top=Bottom=12 -->

<!-- 四个方向分别指定 -->
<Border Padding="16,12,16,20">...</Border>
<!-- 顺序: Left, Top, Right, Bottom -->

<!-- 使用 Thickness -->
<Border>
  <Border.Padding>
    <Thickness Left="16" Top="12" Right="16" Bottom="20"/>
  </Border.Padding>
</Border>

安全区域示例

天气组件示例:

<Border Width="200" Height="150"
        Background="{DynamicResource CardBackgroundBrush}"
        CornerRadius="8"
        Padding="16">
  
  <Grid RowDefinitions="Auto,*,Auto">
    
    <!-- 顶部:位置信息(距离顶边 16px -->
    <TextBlock Grid.Row="0"
               Text="📍 北京"
               FontSize="14"/>
    
    <!-- 中间:主要信息 -->
    <StackPanel Grid.Row="1"
                VerticalAlignment="Center"
                HorizontalAlignment="Center">
      <TextBlock Text="☀️" FontSize="48"/>
      <TextBlock Text="25°C" FontSize="32"/>
    </StackPanel>
    
    <!-- 底部:操作按钮(距离底边 16px -->
    <StackPanel Grid.Row="2"
                Orientation="Horizontal"
                HorizontalAlignment="Right"
                Spacing="8">
      <Button Content="🔄" Padding="8,4"/>
      <Button Content="⚙️" Padding="8,4"/>
    </StackPanel>
    
  </Grid>
  
</Border>

可视化布局:

┌────────────────────────────────┐
│ ◄─── 16px ───►                 │ ▲
│ ▲                              │ │
│ │  📍 北京                     │ │ 16px
│ │                              │ │
│ │         ☀️                   │ ▼
│ 16px      25°C                 │
│ │         晴                   │
│ │                              │ ▲
│ │            [🔄] [⚙️]        │ │ 16px
│ ▼                              │ │
│                 ◄─── 16px ───► │ ▼
└────────────────────────────────┘

📏 间距系统

间距标准

阑山桌面使用 4px 基础网格,所有间距都是 4 的倍数。

名称 用途 使用场景
XXS 2px 最小间距 边框到内容、图标微调
XS 4px 紧密间距 相邻标签、图标与文字
S 8px 小间距 相关元素之间
M 12px 中间距 元素组之间
L 16px 大间距 区块之间、安全边距
XL 24px 超大间距 重要区块分隔
XXL 32px 巨大间距 页面级分隔

间距使用场景

1. 垂直间距Vertical Spacing

<StackPanel Spacing="8">
  <!-- 元素 1 -->
  <TextBlock Text="标题"/>
  
  <!-- ↕ 8px 间距 -->
  
  <!-- 元素 2 -->
  <TextBlock Text="内容"/>
  
  <!-- ↕ 8px 间距 -->
  
  <!-- 元素 3 -->
  <Button Content="操作"/>
</StackPanel>

垂直间距指南:

相关元素(标题和内容):     8px
不同区块:                   16px
独立功能区:                 24px

示例:
┌──────────────────┐
│ 📍 北京          │ ← 标题
│ ↕ 8px            │
│ 今天天气不错     │ ← 内容
│ ↕ 16px           │ ← 区块分隔
│ ☀️               │
│ 25°C             │
│ ↕ 16px           │ ← 区块分隔
│ [刷新] [设置]    │
└──────────────────┘

2. 水平间距Horizontal Spacing

<StackPanel Orientation="Horizontal" Spacing="8">
  <!-- 元素 1 -->
  <Button Content="按钮1"/>
  
  <!-- ↔ 8px 间距 -->
  
  <!-- 元素 2 -->
  <Button Content="按钮2"/>
</StackPanel>

水平间距指南:

图标和文字:     4px
相关按钮:       8px
独立按钮:       12px

示例:
[🔄] ← 4px → 刷新    ← 8px →    [⚙️] ← 4px → 设置

3. 网格间距Grid Spacing

<Grid ColumnDefinitions="*,8,*" RowDefinitions="*,8,*">
  <!-- 列间距: 8px, 行间距: 8px -->
  
  <Border Grid.Column="0" Grid.Row="0" Background="Red"/>
  <Border Grid.Column="2" Grid.Row="0" Background="Blue"/>
  <Border Grid.Column="0" Grid.Row="2" Background="Green"/>
  <Border Grid.Column="2" Grid.Row="2" Background="Yellow"/>
</Grid>

AXAML 间距资源

<!-- 定义间距资源 -->
<ResourceDictionary>
  <Thickness x:Key="SpacingXXS">2</Thickness>
  <Thickness x:Key="SpacingXS">4</Thickness>
  <Thickness x:Key="SpacingS">8</Thickness>
  <Thickness x:Key="SpacingM">12</Thickness>
  <Thickness x:Key="SpacingL">16</Thickness>
  <Thickness x:Key="SpacingXL">24</Thickness>
  <Thickness x:Key="SpacingXXL">32</Thickness>
</ResourceDictionary>

<!-- 使用间距资源 -->
<Border Margin="{StaticResource SpacingL}">
  <StackPanel Spacing="8">
    <!-- 内容 -->
  </StackPanel>
</Border>

🔲 网格系统

4px 基础网格

所有元素的位置、尺寸、间距都应该对齐到 4px 的倍数

0px   4px   8px   12px  16px  20px  24px  28px  32px
│     │     │     │     │     │     │     │     │
▼     ▼     ▼     ▼     ▼     ▼     ▼     ▼     ▼
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│     │     │     │     │     │     │     │     │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│     │     │     │     │     │     │     │     │

为什么是 4px

  • 足够小,提供精细控制
  • 是 8 和 16 的因子,便于计算
  • 符合 Windows 11 设计规范
  • 在高 DPI 屏幕上显示良好

对齐示例

❌ 错误:未对齐网格
┌──────────────┐
│ Padding: 15px│  ← 15 不是 4 的倍数
│ Width: 203px │  ← 203 不是 4 的倍数
└──────────────┘

✅ 正确:对齐到网格
┌──────────────┐
│ Padding: 16px│  ← 16 = 4 × 4
│ Width: 200px │  ← 200 = 4 × 50
└──────────────┘

常用尺寸

符合 4px 网格的常用尺寸:

用途 尺寸选项px
按钮高度 28, 32, 36, 40
图标尺寸 12, 16, 20, 24, 32, 48
组件宽度 120, 160, 200, 240, 280, 320, 400
组件高度 80, 120, 160, 200, 240, 280, 320

📦 组件尺寸规范

最小尺寸

┌─────────────────────┐
│ 最小宽度: 120px     │
│ 最小高度: 80px      │
│                     │
│ 保证可读性和可用性   │
└─────────────────────┘

最小尺寸要求:

  • 宽度 ≥ 120px - 保证文字不会过度换行
  • 高度 ≥ 80px - 保证内容有足够空间
  • 按钮 ≥ 32×32px - 保证可点击性

推荐尺寸

小型组件120-150px:

┌──────────────┐
│ 📍 北京      │
│              │
│     ☀️       │
│    25°C      │
└──────────────┘
120×80 - 150×100
适合: 单一信息、时钟、倒计时

中型组件200-300px:

┌────────────────────────┐
│ 📍 北京                │
│                        │
│         ☀️             │
│        25°C            │
│        晴              │
│                        │
│ 今天: 18-30°C          │
│ 湿度: 60% 风速: 3m/s   │
│                        │
│            [🔄] [⚙️]  │
└────────────────────────┘
200×150 - 300×250
适合: 天气、日历、待办、便签

大型组件350-500px:

┌────────────────────────────────────────┐
│ 📅 本周日程                            │
│                                        │
│ 周一                                   │
│ 09:00 - 10:00  团队会议                │
│ 14:00 - 15:30  项目评审                │
│                                        │
│ 周二                                   │
│ 10:00 - 11:00  客户沟通                │
│ ...                                    │
│                                        │
│                         [查看更多]      │
└────────────────────────────────────────┘
350×300 - 500×400
适合: 日程、系统监控、新闻列表

宽高比建议

组件类型 推荐比例 示例尺寸
正方形 1:1 120×120, 200×200
横向 4:3 200×150, 320×240
宽屏 16:9 320×180, 400×225
竖向 3:4 150×200, 240×320

🎯 响应式布局

尺寸适配

组件应该优雅地适配不同尺寸:

public class WeatherComponent : ComponentBase
{
    // 监听尺寸变化
    protected override void OnSizeChanged(Size newSize)
    {
        if (newSize.Width < 180)
        {
            // 小尺寸:简化布局
            ShowCompactLayout();
        }
        else if (newSize.Width < 300)
        {
            // 中等尺寸:标准布局
            ShowNormalLayout();
        }
        else
        {
            // 大尺寸:详细布局
            ShowDetailedLayout();
        }
    }
}

内容裁剪策略

文本裁剪:

<!-- 单行文本,超出显示省略号 -->
<TextBlock Text="这是一段很长的文字..."
           TextTrimming="CharacterEllipsis"
           MaxLines="1"/>

<!-- 多行文本,最多显示 2 行 -->
<TextBlock Text="这是一段很长的文字..."
           TextWrapping="Wrap"
           TextTrimming="CharacterEllipsis"
           MaxLines="2"/>

内容溢出处理:

<!-- 使用 ScrollViewer 处理溢出 -->
<ScrollViewer MaxHeight="200"
              VerticalScrollBarVisibility="Auto">
  <ItemsControl ItemsSource="{Binding Items}">
    <!-- 列表项 -->
  </ItemsControl>
</ScrollViewer>

断点设计

断点名称 宽度范围 布局策略
XS < 160px 极简布局,只显示核心信息
S 160-240px 简化布局,隐藏次要信息
M 240-360px 标准布局,显示主要信息
L 360-480px 详细布局,显示完整信息
XL > 480px 丰富布局,显示扩展信息

响应式示例

小尺寸(< 160px:

┌──────────┐
│   ☀️     │
│   25°C   │
└──────────┘
只显示图标和温度

中尺寸200px:

┌────────────────┐
│ 📍 北京        │
│                │
│      ☀️        │
│     25°C       │
│      晴        │
│                │
│      🔄  ⚙️    │
└────────────────┘
显示位置、天气、操作

大尺寸300px:

┌──────────────────────────┐
│ 📍 北京                  │
│                          │
│         ☀️               │
│        25°C              │
│         晴               │
│                          │
│ 今天: 18-30°C            │
│ 湿度: 60% 风速: 3m/s     │
│ 空气质量: 良              │
│                          │
│         [刷新] [设置]     │
└──────────────────────────┘
显示详细信息

📐 对齐指南

水平对齐

<!-- 左对齐 -->
<StackPanel HorizontalAlignment="Left">
  <TextBlock Text="左对齐"/>
</StackPanel>

<!-- 居中对齐 -->
<StackPanel HorizontalAlignment="Center">
  <TextBlock Text="居中对齐"/>
</StackPanel>

<!-- 右对齐 -->
<StackPanel HorizontalAlignment="Right">
  <TextBlock Text="右对齐"/>
</StackPanel>

<!-- 拉伸(占满宽度) -->
<StackPanel HorizontalAlignment="Stretch">
  <TextBlock Text="拉伸"/>
</StackPanel>

垂直对齐

<!-- 顶部对齐 -->
<Grid>
  <StackPanel VerticalAlignment="Top">
    <TextBlock Text="顶部"/>
  </StackPanel>
</Grid>

<!-- 居中对齐 -->
<Grid>
  <StackPanel VerticalAlignment="Center">
    <TextBlock Text="居中"/>
  </StackPanel>
</Grid>

<!-- 底部对齐 -->
<Grid>
  <StackPanel VerticalAlignment="Bottom">
    <TextBlock Text="底部"/>
  </StackPanel>
</Grid>

对齐最佳实践

✅ 好的对齐:
┌──────────────────┐
│ 标题             │ ← 左对齐
│                  │
│       25°C       │ ← 居中对齐
│                  │
│        [按钮]    │ ← 右对齐
└──────────────────┘

❌ 差的对齐:
┌──────────────────┐
│   标题           │ ← 随意对齐
│                  │
│  25°C            │ ← 不一致
│                  │
│      [按钮]      │ ← 混乱
└──────────────────┘

🛠️ 实用工具

布局调试

<!-- 开发时显示边界 -->
<Border BorderBrush="Red" BorderThickness="1">
  <StackPanel>
    <!-- 内容 -->
  </StackPanel>
</Border>

<!-- 显示网格线 -->
<Grid ShowGridLines="True">
  <!-- 内容 -->
</Grid>

布局助手类

public static class LayoutHelper
{
    // 对齐到 4px 网格
    public static double AlignToGrid(double value)
    {
        return Math.Round(value / 4) * 4;
    }
    
    // 计算安全区域
    public static Thickness SafeArea(double padding = 16)
    {
        return new Thickness(padding);
    }
    
    // 响应式尺寸
    public static bool IsCompact(double width)
    {
        return width < 180;
    }
    
    public static bool IsNormal(double width)
    {
        return width >= 180 && width < 300;
    }
    
    public static bool IsExpanded(double width)
    {
        return width >= 300;
    }
}

布局检查清单

发布前请检查:

安全区域

  • 上下左右至少 16px 边距
  • 内容不会紧贴边缘
  • 圆角区域没有被裁切

间距

  • 使用 4px 基础网格
  • 相关元素间距 8px
  • 区块间距 16px
  • 间距统一一致

尺寸

  • 最小宽度 ≥ 120px
  • 最小高度 ≥ 80px
  • 按钮尺寸 ≥ 32×32px
  • 尺寸是 4 的倍数

对齐

  • 元素精确对齐
  • 左右边距对称
  • 文字基线对齐
  • 视觉平衡

响应式

  • 小尺寸下正常显示
  • 大尺寸下充分利用空间
  • 文本溢出正确处理
  • 图片按比例缩放

📖 相关文档


记住: 安全区域 16px间距基于 4px 网格,一切对齐精确。