《lvgl基础学习 —— flex和grid》
1.为什么要学布局
如果只用lv_obj_set_pos(obj, x, y)和lv_obj_set_pos(obj, x, y)
会发生什么?
-
分辨率一变 → 全乱
-
文案长度变 → 重叠
-
加一个控件 → 全部重算坐标
-
工程越大 → 越难维护
布局 = UI “自动排版”
LVGL的两种核心布局
布局 适合场景 类比 Flex 列表 / 设置页 / 线性排列 CSS flexbox Grid 表格 / 键盘 / 九宫格 表格布局
90% 的界面 = Flex
Grid 用在“很规整”的地方
Flex
Flex是把子控件按“行或列”自动排列。
你只需要决定:
-
横向 or 纵向
-
对齐方式
-
间距
Flex的API基本用法:
创建一个容器(container)
lv_obj_t *cont = lv_obj_create(lv_scr_act()); lv_obj_set_size(cont, 300, 200); lv_obj_center(cont);
启动Flex布局:
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
设置Flex方向:
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); // 纵向 // 或 lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW); // 横向
demo:三个按钮,自动竖着排
void ui_flex_demo(void) { lv_obj_t *cont = lv_obj_create(lv_scr_act()); lv_obj_set_size(cont, 220, 200); lv_obj_center(cont); lv_obj_set_layout(cont, LV_LAYOUT_FLEX); lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(cont, LV_FLEX_ALIGN_START, // 主轴 LV_FLEX_ALIGN_CENTER, // 交叉轴 LV_FLEX_ALIGN_CENTER // 行对齐 ); for(int i = 0; i < 3; i++) { lv_obj_t *btn = lv_btn_create(cont); lv_obj_set_size(btn, 180, 50); lv_obj_t *label = lv_label_create(btn); lv_label_set_text_fmt(label, "Button %d", i + 1); lv_obj_center(label); } }
Flex对齐规则
主轴(main axis):ROW横向 COLUMN纵向
LV_FLEX_ALIGN_START
LV_FLEX_ALIGN_CENTER
LV_FLEX_ALIGN_END
LV_FLEX_ALIGN_SPACE_EVENLY
交叉轴(cross axis):与主轴垂直
Flex非常适合“设置界面”
实例结构:
[ Label ][ Switch ]
[ Label ][ Slider ]
[ Label ][ Switch ]
这类页面 → Flex + 嵌套 Flex
Grid布局
Grid就是按“行 x 列”精准摆放控件。
你要先定义:
-
有几列
-
有几行
-
每个控件在哪个格子
Grid的API基本用法
定义行列:
static lv_coord_t col_dsc[] = {100, 100, LV_GRID_TEMPLATE_LAST}; static lv_coord_t row_dsc[] = {50, 50, LV_GRID_TEMPLATE_LAST};
创建容器并启用Grid:
lv_obj_t *cont = lv_obj_create(lv_scr_act()); lv_obj_set_size(cont, 220, 120); lv_obj_center(cont); lv_obj_set_layout(cont, LV_LAYOUT_GRID); lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
放控件到指定格子:
lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1 );
demo: 2 x 2按钮
void ui_grid_demo(void) { static lv_coord_t col[] = {120, 120, LV_GRID_TEMPLATE_LAST}; static lv_coord_t row[] = {60, 60, LV_GRID_TEMPLATE_LAST}; lv_obj_t *cont = lv_obj_create(lv_scr_act()); lv_obj_set_size(cont, 260, 150); lv_obj_center(cont); lv_obj_set_layout(cont, LV_LAYOUT_GRID); lv_obj_set_grid_dsc_array(cont, col, row); for(int i = 0; i < 4; i++) { lv_obj_t *btn = lv_btn_create(cont); lv_obj_set_grid_cell(btn, LV_GRID_ALIGN_CENTER, i % 2, 1, LV_GRID_ALIGN_CENTER, i / 2, 1 ); lv_obj_t *label = lv_label_create(btn); lv_label_set_text_fmt(label, "B%d", i + 1); lv_obj_center(label); } }
Flex vs Grid:怎么选?(工程经验)
✅ 用 Flex 的情况(优先)
-
设置页
-
菜单列表
-
表单
-
垂直 / 水平排列
✅ 用 Grid 的情况
-
键盘
-
计算器
-
九宫格
-
仪表盘
👉 先想 Flex,实在不行再 Grid
新手最常见的坑(一定要避)
❌ 1️⃣ 给子对象手动设 pos
→ 布局会覆盖它
❌ 2️⃣ 容器没设 size
→ 子对象挤成一团
❌ 3️⃣ 一个页面全用 grid
→ 维护噩梦
❌ 4️⃣ 不拆 container
→ 层级混乱
浙公网安备 33010602011771号