mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 15:44:25 +08:00
18 KiB
18 KiB
布局规范
本文档详细说明组件布局规范,包括安全区域、间距系统、网格系统和响应式布局。
🎯 布局目标
良好的布局应该:
- ✅ 内容不会被截断或溢出
- ✅ 视觉元素对齐整齐
- ✅ 留白充足,不拥挤
- ✅ 适配不同的组件尺寸
- ✅ 易于维护和扩展
📐 安全区域(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 网格,一切对齐精确。