LVGL学习笔记(四)
2026/8/11 2:17:49 网站建设 项目流程

LVGL学习笔记(四)

属性与布局

前言

在前一篇学习笔记中,我们成功创建了一个标签部件,并且在画面上显示hello world,但是在工程中一个界面常常不只有单个部件(对象),而是多个不同功能的部件(对象)组合在一起的。在这种情况下,我们就必须考虑部件的摆放和部件与部件之间大小设置和页面布局了。

这一篇我们围绕按键部件的属性、多个按键之间的布局来阐述相关概念。最后创建一个简易底部按钮工具栏的项目界面来演示功能的实现。

  • 什么是对象的属性?

    **属性用来修饰控件尺寸、位置、外观、交互的。**在之间的笔记中,我们对象将对象比作一个“积木块”一个实实在在的控件,那么属性就是这个“积木块”的大小、颜色、形状等具体信息。具体来说:

    对象:一个实实在在的部件(按钮、标签、容器、滑块)。

    属性:用来描述这个对象长什么样、位置、大小、颜色、开关状态、文本、透明度的各项特征参数。

    可以将属性分为如下几类:

    • 基本属性

      LVGL在设计的时候参考了CSS的盒子模型相关概念,所谓盒子模型就是每一个 LVGL 控件 (对象) 就是一个方块盒子,如下图所示:

      盒子由内往外一共四层,分别是:

      1.内容:存放真正东西:按钮文字、图片、标签文字。宽高默认就是内容区域的尺寸。

      2.内边距:内容和自己边框之间的留白。

      3.边框:盒子的边线、圆角边框。边框会占盒子的空间厚度。

      4.外边距:当前盒子 和 旁边别的控件之间的间隔。

      基本属性包括对象的位置尺寸属性,例如对象的位置、大小、对齐方式、内外边距、布局方式等。由于部件有多种实现方式,故属性的函数也有许多,这里不做一一列举,感兴趣的可以参考LGVL提供的官方手册,这里只介绍作者习惯使用的。

      下面主要分析一下基本属性用到的函数,如下表所示:

      函数描述
      lv_obj_set_pos(对象指针,x坐标,y坐标)设置左上角坐标位置
      lv_obj_set_size(对象指针, 高度, 宽度);设置对象尺寸大小
      lv_obj_align(对象指针,对齐模式,x轴偏移量,y轴偏移量).设置对齐方式
      lv_pct(value)将一个值转换为百分比
      lv_obj_set_style_pad_all(对象指针,内边距值,应用式样)设置对象所有内边距
      lv_style_set_border_width(对象指针, 宽度);设置边框宽度
      lv_style_set_border_color(对象指针, 颜色)设置边框颜色
      lv_style_set_border_opa(对象指针,透明度)设置边框透明度
      lv_style_set_radius(对象指针,圆角半径)设置边框圆角
    • 样式属性

      样式属性是一个大的分类,其中又可以分为大小位置属性、填充属性、背景属性、边框属性、轮廓属性、阴影属性、图片属性、线条属性、圆弧属性和文本属性等等。

      式样属性的其中一个特点就是lv_obj_set_style_xxx(本地样式)或者 lv_style_set_xxx (普通样式)的格式,因此我们在设置某个样式的时候,只需要记住关键的单词即可,例如宽度(width)设置的函数为:lv_obj_set_style_width。

      上述基本属性中边框对象部分也可以归类到式样属性中来,由于式样属性用到的函数太多,只能在之后的笔记中用到时再进行介绍。

      这里据几个常用的进行介绍:

      函数描述
      lv_obj_set_style_text_font(对象指针,字体大小,状态)设置字体大小
      lv_obj_set_style_text_color(对象指针,字体大小,状态)设置文本颜色
      lv_obj_add_state(对象指针, 状态);设置组件的状态
      lv_obj_clear_statee(对象指针, 状态)清除组件的状态

      式样的特点:

      1.复用与级联: 一个样式可以被多个对象使用。
      2.继承: 如果对象没有指定某个属性(如文本颜色),它会从父对象继承。
      3.本地样式: 对象可以拥有高优先级的“本地样式”,用于进行个别的、独特的样式设置。
      4.过渡效果: 样式支持过渡动画,可以在状态改变时产生平滑的视觉效果。

    • 滚动属性

      在 LVGL 中,任何对象都是支持滚动的。如果一个对象在其父对象的区域之外,则该父 对象将变为可滚动的,并且在其内部出现滚动条。滚动属性的相关介绍需要等理解了事件的相关概念后才方便演示,这里不过多表述。

    • 动画属性

      优秀的过渡动画可以让用户的 GUI 变得更具高级感。在 LVGL 中,用户可指定动画的开 始值和结束值,该动画将通过回调函数来处理。动画属性的相关介绍需要等理解了定时器的相关概念后才方便演示,这里同样不过多表述。

    • 其他属性

      由于状态和事件概念还没有阐述,所以先将状态属性和事件属性归到其他属性中。

      除此之外,由于LVGL还在不断地更新版本,V9中出现许多新的属性类型,无法用上述的属性进行归类,就将其归如其他属性中。

  • LVGL 核心对象属性分为几种?有什么区别?具体在项目中如何使用?

    属性可以分为两种,分别是对象直接属性和初始化属性。其区别是对象直接属性可以调用函数lv_obj_xxx()直接修改。而初始化属性需要先初始化样式,再挂载到部件中去。

    项目当中通用使用步骤:

    1. 创建父容器;设置大小、对齐、开启布局等
    2. 初始化公共样式,配置盒子模型、圆角、间距等
    3. 创建子控件,设置尺寸
    4. 给控件挂载常态 / 按压样式
    5. 设置可见性、启用状态、点击回调

    一般项目都存在前两步骤,后面的步骤根据项目实际情况灵活增减。

  • LVGL 布局方式有哪几种?分别有什么区别?具体的使用场景是什么?

    布局本质就是管控子控件位置、大小。布局可以分为默认布局、Flex弹性布局和Grid网格布局三种,下面分别进行介绍:

    1.默认布局

    LVGL 的布局设计深受 CSS 启发,其主要内容涉及 3 个方面:坐标位置、大小以及对齐方式。如果在创建控件时不给控件安排布局,那么控件默认会被放在父容器的左上角。

    可以使用 lv_obj_set_pos(obj, x, y) 调整一个对象的位置(或者使用类似的函数单独调整一个方向的坐标),将它放在相对父对象左上角的合适位置。

    默认布局的对齐模式,其内容非常丰富,如下表所示:

    内部对齐:

    对齐模式描述
    LV_ALIGN_TOP_LEFT顶部左边对齐
    LV_ALIGN_TOP_MID顶部中间对齐
    LV_ALIGN_TOP_RIGHT顶部右边对齐
    LV_ALIGN_BOTTOM_LEFT底部左边对齐
    LV_ALIGN_BOTTOM_MID底部中间对齐
    LV_ALIGN_BOTTOM_RIGHT底部右边对齐
    LV_ALIGN_LEFT_MID左边中间对齐
    LV_ALIGN_RIGHT_MID右边中间对齐
    LV_ALIGN_CENTER中间对齐

    外部对齐:

    对齐模式描述
    LV_ALIGN_OUT_TOP_LEFT在外顶部左边对齐
    LV_ALIGN_OUT _TOP_MID在外顶部中间对齐
    LV_ALIGN_OUT _TOP_RIGHT在外顶部右边对齐
    LV_ALIGN_OUT _BOTTOM_LEFT在外底部左边对齐
    LV_ALIGN_OUT _BOTTOM_MID在外底部中间对齐
    LV_ALIGN_OUT _BOTTOM_RIGHT在外底部右边对齐
    LV_ALIGN_OUT _LEFT_MID在外左边中间对齐
    LV_ALIGN_OUT _RIGHT_MID在外右边中间对齐

    对齐方式如下图所示:

    从图片中可以看到,控件之间不仅可以内对齐,也可以外对齐。如果两个控件间没有包含关系也不要紧,可以使用 lv_obj_align_to(obj, base, align, x_ofs, y_ofs); 设置两个控件的相对对齐方式。

    默认布局这种布局方式非常死板,因为绝对坐标一旦设定就不能自动调整,而且当控件数量较多时,也很难确定合适的坐标值,但对于控件较少的场景,默认布局已经可以满足需求了。

    2.Flex弹性布局

    Flex 布局,是一种可以简便、完整、响应式地实现各种页面布局,它是 CSS 的一个重点应用。

    启用 Flex 布局:在 lv_conf.h 文件中把 LV_USE_FLEX 配置项置 1 即可启用 Flex 布局。

    /*A layout similar to Flexbox in CSS.*/#define LV_USE_FLEX1

    flex布局配置项

    轨道:行或列。

    主轴:行或列,对象放置的方向。

    交叉轴:垂直于主轴。

    换行/换列:如果轨道中没有更多空间,则开始新轨道

    增长:如果设置在一个项目上,它将增长以填充轨道上的剩余空间。

    间隙:行和列或轨道上的对象之间的空间。

    flex布局相关函数

    在LVGL中,所有与 Flex 相关的值都是底层的样式属性,这些与 Flex 相关的样式属性函数 如下表所示:

    函数描述
    lv_style_set_flex_flow()设置 Flex 流动布局
    lv_style_set_flex_main_place()设置主轴
    lv_style_set_flex_cross_place()设置交叉轴
    lv_style_set_flex_track_place()设置轨道轴
    lv_style_set_flex_grow()设置增长

    下面挨个介绍对应函数

    设置 Flex 流动布局

    如果不添加任何布局方式,那么所有的控件都会堆放在左上角。flex 布局可以将一些控件按行或列均匀布局,并且可以自动调整它们的间距。

    可以给一个容器设置一个 flex-flow 属性,这样容器就可以使用 flex 布局方式:

    voidlv_obj_set_flex_flow(lv_obj_t*obj,lv_flex_flow_tflow);

    参数说明:

    形参说明
    obj指向设置Flex布局的对象
    flowflex 布局方式

    该函数无返回值。

    flow形参的转入值下表所示:

    配置项描述
    LV_FLEX_FLOW_ROW将子类们排成一行并不换行
    LV_FLEX_FLOW_ROW_WRAP将子类们排成一行并换行
    LV_FLEX_FLOW_ROW_REVERSE将子类们排成一行并不换行且顺序相反
    LV_FLEX_FLOW_ROW_WRAP_REVERSE将子类们排成一行并换行且顺序相反
    LV_FLEX_FLOW_COLUMN将子类们排成一列并不换行
    LV_FLEX_FLOW_COLUMN_WRAP将子类们排成一列并换行
    LV_FLEX_FLOW_COLUMN_REVERSE将子类们排成一列并不换行且顺序相反
    LV_FLEX_FLOW_COLUMN_WRAP_REVERSE将子类们排成一列并换行且顺序相反

    flex布局的对齐

    以上 flex 布局中,各控件的尺寸和间距都是固定的,并且第一个控件依然会出现在左上角。如果

    可以使用**lv_obj_set_flex_align()**函数进行修改。

    voidlv_obj_set_flex_align(lv_obj_t*obj,lv_flex_align_tmain_place,lv_flex_align_tcross_place,lv_flex_align_ttrack_place)

    参数说明:

    形参说明
    obj指向设置对齐的对象
    main_place主轴上的对象对齐
    cross_place交叉轴上的对象对齐
    track_place行/列交叉轴上的对象对齐

    该函数无返回值。

    main_place、cross_place 和 track_cross_place 形参的转入值如下表所示:

    配置项描述
    LV_FLEX_ALIGN_START水平方向左上和垂直上方向上(默认)
    LV_FLEX_ALIGN_END水平方向右侧和垂直底部
    LV_FLEX_ALIGN_CENTER居中
    LV_FLEX_ALIGN_SPACE_EVENLY任何两个对象之间的间距(它们的边缘空间相等),但不适用于 track_cross_place 形参
    LV_FLEX_ALIGN_SPACE_AROUND对象在轨道上均匀分布,周围空间相等,但不适用于 track_cross_place 形参
    LV_FLEX_ALIGN_SPACE_BETWEEN对象在轨道上均匀分布:第一个对象在开始行 , 最后一个项目在结束行 , 但不适用 于 track_cross_place 形参

    flex布局弹性增长

    简单来说,flex 弹性增长 (flex_grow):当父容器还有剩余空余空间的时候,规定子控件瓜分剩下空位的权重。

    例如,父容器宽度 300px,里面并排 3 个按钮,按钮基础宽度各 60px。
    那么,总占用为60×3 = 180px,剩余空闲空间 = 300-180 =120px
    得到flex‑grow 就是决定这 120 多余空间怎么分给各个子按钮。

    具体函数原型如下:

    voidlv_obj_set_flex_grow(lv_obj_t*obj,uint8_tgrow)

    函数形参说明如下:

    形参说明
    obj需要设置的子对象
    grow大于 0 表示可扩展,值越大分配的剩余空间越多;0 表示不扩展。

    3.Grid网格布局

    flexbox是 一种一维的布局,是因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列, 但是 Grid 布局是一种二维布局,它可以同时处理行和列上的布局。

    要使用网格布局需要在配置文件 lv_conf.h 中启用 LV_USE_GRID 宏定义,否则使用弹性布局相关的内容将提示未定义的类型。

    /*A layout similar to Grid in CSS.*/#define LV_USE_GRID1

    Grid布局配置项

    轨道(tracks):行或列。

    空闲单元(FR):如果在轨道上设置了大小,FR 它将增长以填充父级的剩余空间。

    间隙(gap):行和列或轨道上的项目之间的空间。

    Grid布局相关函数

    在LVGL中,所有与 Grid 相关的值都是底层的样式属性,这些与 Grid 相关的样式属性函数如下所示:

    函数描述
    lv_obj_set_style_grid_column_dsc_array()绑定列配置
    lv_obj_set_style_grid_row_dsc_array()绑定行配置
    lv_obj_set_layout()启用 Grid 布局
    lv_obj_set_grid_cell()设置弹簧拉伸
    lv_obj_set_grid_align()设置Grid 布局对齐方式

    网格描述符

    使用 Grid 布局的第一步,是通过数组定义网格的行高和列宽,数组最后一个元素必须为 LV_GRID_TEMPLATE_LAST。

    示例代码如下:

    // 定义列描述:2列,宽度分别为100px、400pxstaticint32_tcolumn_dsc[]={100,400,LV_GRID_TEMPLATE_LAST};// 定义行描述:3行,每行高度100pxstaticint32_trow_dsc[]={100,100,100,LV_GRID_TEMPLATE_LAST};

    使用 Grid 布局的第二步,就是绑定行和列数组

    示例代码如下:

    // 设置对象网格布局行描述数组lv_obj_set_style_grid_column_dsc_array(cont,col_dsc,0);// 设置对象网格布局列描述数组lv_obj_set_style_grid_row_dsc_array(cont,row_dsc,0);

    最后,启动Grid 布局。LVGL 内置了几种简单布局,可通过函数lv_obj_set_layout()快速启用

    示例代码如下:

    lv_obj_set_layout(btn,LV_LAYOUT_GRID);

    网格布局对齐方式

    通过核心函数设置子控件在网格中的位置、对齐方式和占用空间。Grid 对齐与 flex 容器对齐标准是类似的,需要注意的是Grid 对齐使用的是 lv_obj_set_grid_align函数并不是 lv_obj_set_flex_align函数。

    对应函数原型如下:

    voidlv_obj_set_grid_align(lv_obj_t*obj,lv_grid_align_tcolumn_align,lv_grid_align_trow_align)

    对应形参如下

    形参说明
    obj指向要对齐的对象
    column_align行对齐
    row_align列对齐

    常用对齐规则有如下几种,分别是:

    LV_GRID_ALIGN_START:左 / 上对齐(默认)
    LV_GRID_ALIGN_END:右 / 下对齐
    LV_GRID_ALIGN_CENTER:居中摆放
    LV_GRID_ALIGN_SPACE_EVENLY:所有间距均等
    LV_GRID_ALIGN_SPACE_AROUND:控件两侧间距相等
    LV_GRID_ALIGN_SPACE_BETWEEN:两端对齐,中间均分

    该函数无返回值

    网格布局的弹簧拉伸

    对应函数原型如下:

    // 函数参数说明lv_obj_set_grid_cell(child,// 要摆放的子控件col_align,// 水平对齐方式col_pos,// 列索引(从0开始)col_span,// 占用列数row_align,// 垂直对齐方式row_pos,// 行索引(从0开始)row_span// 占用行数);

    column_align和 row_align 确定如何在其单元格中对齐子项。 可能的值为:

    LV_GRID_ALIGN_START 表示在水平方向和垂直方向的顶部左侧。 (默认)

    LV_GRID_ALIGN_END 表示水平和底部垂直

    LV_GRID_ALIGN_CENTER 只是居中

    colum_pos 和 row_pos 表示应该放置项目中单元格的从零开始的索引。

    colum_span 和 row_span 表示该项目应该从起始单元格开始包含多少个轨道。 必须 > 1.

    综上所述,三种布局各自适合的使用场景如下:

    布局适用场景
    NONE自由拖拽、少量控件
    Flex菜单栏、列表、横向按钮组、状态栏
    Grid数字键盘、设置九宫格、表格 UI

接下来举上述的例子,使用flex布局设置一个一个简易底部按钮工具栏的界面

参考代码如下:

// 封装创建按钮函数lv_obj_t*create_btn(lv_obj_t*parent,constchar*txt){lv_obj_t*btn=lv_btn_create(parent);lv_obj_set_flex_grow(btn,1);lv_obj_set_style_pad_all(btn,8,0);lv_obj_t*label=lv_label_create(btn);lv_label_set_text(label,txt);lv_obj_center(label);//移除多余括号returnbtn;}voidlv_mainstart(void){// 1. 创建底层容器,底部工具栏lv_obj_t*bar=lv_obj_create(lv_scr_act());// 设置容器尺寸,铺满屏幕宽度、高度80pxlv_obj_set_size(bar,LV_PCT(100),80);// 对齐到屏幕底部lv_obj_align(bar,LV_ALIGN_BOTTOM_MID,0,0);// 设置内边距lv_obj_set_style_pad_all(bar,10,0);// 开启横向Flex布局lv_obj_set_layout(bar,LV_LAYOUT_FLEX);lv_obj_set_flex_flow(bar,LV_FLEX_FLOW_ROW);// 子控件之间均分剩余空间lv_obj_set_flex_align(bar,LV_FLEX_ALIGN_SPACE_EVENLY,LV_FLEX_ALIGN_CENTER,LV_FLEX_ALIGN_CENTER);// 创建3个功能按键create_btn(bar,"home");create_btn(bar,"setting");create_btn(bar,"about");}

演示结果:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询