《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
→ 层级混乱

 

 

posted @ 2025-12-19 11:20  一个不知道干嘛的小萌新  阅读(10)  评论(0)    收藏  举报