布局系统¶
概述¶
EmbeddedGUI 提供三种布局方式:手动布局、LinearLayout 线性布局和 GridLayout 网格布局。手动布局通过直接设置坐标和尺寸实现,适合简单场景;自动布局容器则负责计算子视图的排列位置,适合动态内容。
手动布局¶
最基础的布局方式,直接指定视图相对于父容器的位置和大小:
// 设置位置(相对父视图左上角)
egui_view_set_position(EGUI_VIEW_OF(&my_label), 10, 20);
// 设置大小
egui_view_set_size(EGUI_VIEW_OF(&my_label), 100, 30);
坐标系统:
原点在父视图内容区域(padding 内侧)的左上角
X 轴向右为正,Y 轴向下为正
单位为像素(
egui_dim_t,即int16_t)
Padding 和 Margin¶
Padding(内边距)¶
定义视图内容区域与视图边界之间的间距。对于容器视图,子视图的坐标原点从 padding 内侧开始。
// 分别设置四边
egui_view_set_padding(EGUI_VIEW_OF(&my_group), 5, 5, 10, 10);
// 左 右 上 下
// 四边统一设置
egui_view_set_padding_all(EGUI_VIEW_OF(&my_group), 8);
Margin(外边距)¶
定义视图与相邻视图之间的间距。在自动布局容器中,margin 参与排列计算。
// 分别设置四边
egui_view_set_margin(EGUI_VIEW_OF(&my_label), 4, 4, 2, 2);
// 四边统一设置
egui_view_set_margin_all(EGUI_VIEW_OF(&my_label), 5);
Padding 与 Margin 的关系¶
+------ 视图边界 (region) ------+
| margin (外) |
| +------ padding (内) ------+ |
| | | |
| | 内容区域 / 子视图 | |
| | | |
| +--------------------------+ |
+-------------------------------+
启用 EGUI_CONFIG_REDUCE_MARGIN_PADDING_SIZE 后,margin/padding 类型从 int16_t 缩减为 int8_t,节省 RAM 但限制范围为 -128~127。
LinearLayout 线性布局¶
egui_view_linearlayout_t 将子视图沿单一方向(水平或垂直)依次排列。
结构体¶
struct egui_view_linearlayout
{
egui_view_group_t base;
uint8_t align_type; // 对齐方式
uint8_t is_auto_width; // 自动调整宽度
uint8_t is_auto_height; // 自动调整高度
uint8_t is_orientation_horizontal; // 0=垂直, 1=水平
};
API¶
API |
说明 |
|---|---|
|
初始化(默认垂直方向) |
|
设置方向 (0=垂直, 1=水平) |
|
设置对齐方式 |
|
启用自动宽度 |
|
启用自动高度 |
对齐方式¶
对齐常量定义在 egui_common.h:
常量 |
值 |
说明 |
|---|---|---|
|
0x02 |
水平左对齐 |
|
0x01 |
水平居中 |
|
0x04 |
水平右对齐 |
|
0x20 |
垂直顶部对齐 |
|
0x10 |
垂直居中 |
|
0x40 |
垂直底部对齐 |
|
0x11 |
水平+垂直居中 |
对齐方式可通过按位或组合,如 EGUI_ALIGN_HCENTER | EGUI_ALIGN_TOP。
Auto Width / Auto Height¶
启用后,容器会根据子视图的总尺寸自动调整自身大小:
垂直布局 +
auto_height:容器高度 = 所有子视图高度之和(含 margin)水平布局 +
auto_width:容器宽度 = 所有子视图宽度之和(含 margin)
参数宏初始化¶
可通过参数宏在编译期初始化:
// 垂直布局,居中对齐
EGUI_VIEW_LINEARLAYOUT_PARAMS_INIT(layout_params, 0, 0, 200, 300, EGUI_ALIGN_HCENTER);
// 水平布局
EGUI_VIEW_LINEARLAYOUT_PARAMS_INIT_H(layout_params_h, 0, 0, 300, 50, EGUI_ALIGN_VCENTER);
// 使用参数初始化
egui_view_linearlayout_init_with_params(EGUI_VIEW_OF(&my_layout), core, &layout_params);
GridLayout 网格布局¶
egui_view_gridlayout_t 将子视图按网格排列,指定列数后自动换行。
结构体¶
struct egui_view_gridlayout
{
egui_view_group_t base;
uint8_t col_count; // 列数
uint8_t align_type; // 对齐方式
};
API¶
API |
说明 |
|---|---|
|
初始化(默认 2 列) |
|
设置列数 |
|
设置对齐方式 |
布局算法¶
GridLayout 的布局逻辑:
将容器宽度等分为
col_count列,每列宽度 =container_width / col_count子视图按添加顺序依次填入单元格
每个子视图在单元格内水平居中
行高取该行中最高子视图的高度(含 margin)
is_gone的子视图不参与布局
参数宏初始化¶
// 3 列网格,居中对齐
EGUI_VIEW_GRIDLAYOUT_PARAMS_INIT(grid_params, 0, 0, 240, 320, 3, EGUI_ALIGN_HCENTER);
egui_view_gridlayout_init_with_params(EGUI_VIEW_OF(&my_grid), core, &grid_params);
嵌套布局示例¶
一个典型的页面布局:顶部标题栏(水平),下方内容区(垂直排列多个卡片)。
static egui_view_linearlayout_t page_layout; // 页面根布局(垂直)
static egui_view_linearlayout_t title_bar; // 标题栏(水平)
static egui_view_label_t title_label;
static egui_view_label_t card_1;
static egui_view_label_t card_2;
static egui_view_label_t card_3;
void page_init(egui_core_t *core)
{
// 页面根布局 - 垂直
egui_view_linearlayout_init(EGUI_VIEW_OF(&page_layout), core);
egui_view_set_position(EGUI_VIEW_OF(&page_layout), 0, 0);
egui_view_set_size(EGUI_VIEW_OF(&page_layout), 240, 320);
egui_view_linearlayout_set_orientation(EGUI_VIEW_OF(&page_layout), 0);
// 标题栏 - 水平居中
egui_view_linearlayout_init(EGUI_VIEW_OF(&title_bar), core);
egui_view_set_size(EGUI_VIEW_OF(&title_bar), 240, 40);
egui_view_linearlayout_set_orientation(EGUI_VIEW_OF(&title_bar), 1);
egui_view_linearlayout_set_align_type(EGUI_VIEW_OF(&title_bar), EGUI_ALIGN_CENTER);
// 标题文字
egui_view_label_init(EGUI_VIEW_OF(&title_label), core);
egui_view_set_size(EGUI_VIEW_OF(&title_label), 100, 30);
egui_view_label_set_text(EGUI_VIEW_OF(&title_label), "My App");
// 卡片
egui_view_label_init(EGUI_VIEW_OF(&card_1), core);
egui_view_set_size(EGUI_VIEW_OF(&card_1), 220, 60);
egui_view_set_margin_all(EGUI_VIEW_OF(&card_1), 5);
egui_view_label_init(EGUI_VIEW_OF(&card_2), core);
egui_view_set_size(EGUI_VIEW_OF(&card_2), 220, 60);
egui_view_set_margin_all(EGUI_VIEW_OF(&card_2), 5);
egui_view_label_init(EGUI_VIEW_OF(&card_3), core);
egui_view_set_size(EGUI_VIEW_OF(&card_3), 220, 60);
egui_view_set_margin_all(EGUI_VIEW_OF(&card_3), 5);
// 构建视图树
egui_view_group_add_child(EGUI_VIEW_OF(&title_bar), EGUI_VIEW_OF(&title_label));
egui_view_group_add_child(EGUI_VIEW_OF(&page_layout), EGUI_VIEW_OF(&title_bar));
egui_view_group_add_child(EGUI_VIEW_OF(&page_layout), EGUI_VIEW_OF(&card_1));
egui_view_group_add_child(EGUI_VIEW_OF(&page_layout), EGUI_VIEW_OF(&card_2));
egui_view_group_add_child(EGUI_VIEW_OF(&page_layout), EGUI_VIEW_OF(&card_3));
}
布局结果:
+--- page_layout (240x320, 垂直) ---+
| +--- title_bar (240x40, 水平) ---+ |
| | [My App] | |
| +--------------------------------+ |
| +--- card_1 (220x60, margin=5) --+ |
| | | |
| +--------------------------------+ |
| +--- card_2 (220x60, margin=5) --+ |
| | | |
| +--------------------------------+ |
| +--- card_3 (220x60, margin=5) --+ |
| | | |
| +--------------------------------+ |
+------------------------------------+